javascript - imagen - Descargue y abra el archivo pdf usando Ajax
descargar imagen con ajax (12)
¿Tienes que hacerlo con Ajax? ¿No sería posible cargarlo en un iframe?
Tengo una clase de acción que genera un pdf. El contentType
está configurado apropiadamente.
public class MyAction extends ActionSupport
{
public String execute() {
...
...
File report = signedPdfExporter.generateReport(xyzData, props);
inputStream = new FileInputStream(report);
contentDisposition = "attachment=/"" + report.getName() + "/"";
contentType = "application/pdf";
return SUCCESS;
}
}
Llamo a esta action
través de una llamada Ajax. No sé cómo entregar esta transmisión al navegador. Intenté algunas cosas pero nada funcionó.
$.ajax({
type: "POST",
url: url,
data: wireIdList,
cache: false,
success: function(response)
{
alert(''got response'');
window.open(response);
},
error: function (XMLHttpRequest, textStatus, errorThrown)
{
alert(''Error occurred while opening fax template''
+ getAjaxErrorString(textStatus, errorThrown));
}
});
Lo anterior da el error:
Su navegador envió una solicitud que este servidor no pudo entender.
Aquí es cómo lo hice funcionar
$.ajax({
url: ''<URL_TO_FILE>'',
success: function(data) {
var blob=new Blob([data]);
var link=document.createElement(''a'');
link.href=window.URL.createObjectURL(blob);
link.download="<FILENAME_TO_SAVE_WITH_EXTENSION>";
link.click();
}
});
Respuesta actualizada usando download.js
$.ajax({
url: ''<URL_TO_FILE>'',
success: download.bind(true, "<FILENAME_TO_SAVE_WITH_EXTENSION>", "<FILE_MIME_TYPE>")
});
Así es como resuelvo este problema.
La respuesta de Jonathan Amend en este artículo me ayudó mucho.
El ejemplo a continuación está simplificado.
Para obtener más detalles, el código fuente anterior puede descargar un archivo utilizando una solicitud JQuery Ajax (GET, POST, PUT, etc.) . También ayuda a cargar parámetros como JSON y a cambiar el tipo de contenido a application / json (mi valor predeterminado) .
La fuente html :
<form method="POST">
<input type="text" name="startDate"/>
<input type="text" name="endDate"/>
<input type="text" name="startDate"/>
<select name="reportTimeDetail">
<option value="1">1</option>
</select>
<button type="submit"> Submit</button>
</form>
Una forma simple con dos entradas de texto, una de selección y un elemento de botón.
La fuente de la página de JavaScript :
<script type="text/javascript" src="JQuery 1.11.0 link"></script>
<script type="text/javascript">
// File Download on form submition.
$(document).on("ready", function(){
$("form button").on("click", function (event) {
event.stopPropagation(); // Do not propagate the event.
// Create an object that will manage to download the file.
new AjaxDownloadFile({
url: "url that returns a file",
data: JSON.stringify($("form").serializeObject())
});
return false; // Do not submit the form.
});
});
</script>
Un evento simple al hacer clic en el botón. Crea un objeto AjaxDownloadFile. La fuente de la clase AjaxDownloadFile está debajo.
La fuente de clase AjaxDownloadFile :
var AjaxDownloadFile = function (configurationSettings) {
// Standard settings.
this.settings = {
// JQuery AJAX default attributes.
url: "",
type: "POST",
headers: {
"Content-Type": "application/json; charset=UTF-8"
},
data: {},
// Custom events.
onSuccessStart: function (response, status, xhr, self) {
},
onSuccessFinish: function (response, status, xhr, self, filename) {
},
onErrorOccured: function (response, status, xhr, self) {
}
};
this.download = function () {
var self = this;
$.ajax({
type: this.settings.type,
url: this.settings.url,
headers: this.settings.headers,
data: this.settings.data,
success: function (response, status, xhr) {
// Start custom event.
self.settings.onSuccessStart(response, status, xhr, self);
// Check if a filename is existing on the response headers.
var filename = "";
var disposition = xhr.getResponseHeader("Content-Disposition");
if (disposition && disposition.indexOf("attachment") !== -1) {
var filenameRegex = /filename[^;=/n]*=(([""]).*?/2|[^;/n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1])
filename = matches[1].replace(/[""]/g, "");
}
var type = xhr.getResponseHeader("Content-Type");
var blob = new Blob([response], {type: type});
if (typeof window.navigator.msSaveBlob !== "undefined") {
// IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed.
window.navigator.msSaveBlob(blob, filename);
} else {
var URL = window.URL || window.webkitURL;
var downloadUrl = URL.createObjectURL(blob);
if (filename) {
// Use HTML5 a[download] attribute to specify filename.
var a = document.createElement("a");
// Safari doesn"t support this yet.
if (typeof a.download === "undefined") {
window.location = downloadUrl;
} else {
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
}
} else {
window.location = downloadUrl;
}
setTimeout(function () {
URL.revokeObjectURL(downloadUrl);
}, 100); // Cleanup
}
// Final custom event.
self.settings.onSuccessFinish(response, status, xhr, self, filename);
},
error: function (response, status, xhr) {
// Custom event to handle the error.
self.settings.onErrorOccured(response, status, xhr, self);
}
});
};
// Constructor.
{
// Merge settings.
$.extend(this.settings, configurationSettings);
// Make the request.
this.download();
}
};
Creé esta clase para agregar a mi biblioteca JS. Es reutilizable Espero que ayude.
En cuanto a la respuesta dada por esta es la lógica correcta para descargar un archivo pdf a través de ajax, pero como otros informan en los comentarios, esta solución es, de hecho, descarga un pdf en blanco.
El motivo de esto se explica en la respuesta aceptada de esta question : jQuery tiene algunos problemas al cargar datos binarios mediante solicitudes AJAX, ya que aún no implementa algunas capacidades HTML5 XHR v2, consulte esta request mejora y esta discussion .
Entonces, usando HTMLHTTPRequest
el código debería verse así:
var req = new XMLHttpRequest();
req.open("POST", "URL", true);
req.responseType = "blob";
req.onload = function (event) {
var blob = req.response;
var link=document.createElement(''a'');
link.href=window.URL.createObjectURL(blob);
link.download="name_for_the_file_to_save_with_extention";
link.click();
}
Este fragmento es para usuarios angulares de js que enfrentarán el mismo problema. Tenga en cuenta que el archivo de respuesta se descarga usando un evento de clic programado. En este caso, los encabezados fueron enviados por el servidor que contiene nombre de archivo y contenido / tipo.
$http({
method: ''POST'',
url: ''DownloadAttachment_URL'',
data: { ''fileRef'': ''filename.pdf'' }, //I''m sending filename as a param
headers: { ''Authorization'': $localStorage.jwt === undefined ? jwt : $localStorage.jwt },
responseType: ''arraybuffer'',
}).success(function (data, status, headers, config) {
headers = headers();
var filename = headers[''x-filename''];
var contentType = headers[''content-type''];
var linkElement = document.createElement(''a'');
try {
var blob = new Blob([data], { type: contentType });
var url = window.URL.createObjectURL(blob);
linkElement.setAttribute(''href'', url);
linkElement.setAttribute("download", filename);
var clickEvent = new MouseEvent("click", {
"view": window,
"bubbles": true,
"cancelable": false
});
linkElement.dispatchEvent(clickEvent);
} catch (ex) {
console.log(ex);
}
}).error(function (data, status, headers, config) {
}).finally(function () {
});
Lo que funcionó para mí es el siguiente código, ya que la función del servidor es recuperar File(memoryStream.GetBuffer(), "application/pdf", "fileName.pdf");:
$http.get( fullUrl, { responseType: ''arraybuffer'' })
.success(function (response) {
var blob = new Blob([response], { type: ''application/pdf'' });
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob); // for IE
}
else {
var fileURL = URL.createObjectURL(blob);
var newWin = window.open(fileURL);
newWin.focus();
newWin.reload();
}
});
No necesariamente necesitas Ajax para esto. Solo un <a>
enlace es suficiente si configura el content-disposition
en el attachment
en el código del lado del servidor. De esta manera, la página principal se mantendrá abierta, si esa era su principal preocupación (¿por qué habría elegido innecesariamente Ajax para esto?). Además, no hay forma de manejar esto de manera muy sincronizada. PDF no es datos de caracteres. Son datos binarios. No puedes hacer cosas como $(element).load()
. Desea utilizar una solicitud completamente nueva para esto. Para ese <a href="pdfservlet/filename.pdf">pdf</a>
es perfectamente adecuado.
Para ayudarlo más con el código del lado del servidor, deberá contar más sobre el idioma utilizado y publicar un fragmento de los intentos de código.
Puedes usar este plugin
jQuery.download = function(url, data, method) {
//url and data options required
if (url && data) {
//data can be string of parameters or array/object
data = typeof data == ''string'' ? data : jQuery.param(data);
//split params into form inputs
var inputs = '''';
jQuery.each(data.split(''&''), function() {
var pair = this.split(''='');
inputs += ''<input type="hidden" name="'' + pair[0] +
''" value="'' + pair[1] + ''" />'';
});
//send request
jQuery(''<form action="'' + url +
''" method="'' + (method || ''post'') + ''">'' + inputs + ''</form>'')
.appendTo(''body'').submit().remove();
};
};
$.download(
''/export.php'',
''filename=mySpreadsheet&format=xls&content='' + spreadsheetData
);
Esto funcionó para mí. Encontrado este plugin aquí
Realmente no creo que ninguna de las respuestas anteriores haya detectado el problema del cartel original. Todos suponen una solicitud GET mientras el póster intentaba PUBLICAR datos y obtener una descarga en respuesta.
En el curso de la búsqueda de una mejor respuesta, encontramos este jQuery Plugin para solicitar descargas de archivos tipo Ajax .
En su "corazón" crea un formulario HTML "temporal" que contiene los datos dados como campos de entrada. Este formulario se adjunta al documento y se publica en la URL deseada. Inmediatamente después, el formulario se elimina nuevamente:
jQuery(''<form action="''+ url +''" method="''+ (method||''post'') +''">''+inputs+''</form>'')
.appendTo(''body'').submit().remove()
Actualizar la respuesta de Mayur parece bastante prometedora y muy simple en comparación con el complemento jQuery al que me refería.
Si tiene que trabajar con el flujo de archivos (por lo tanto, no hay un PDF guardado físicamente) como nosotros y desea descargar el PDF sin recargar la página, la siguiente función nos funciona:
HTML
<div id="download-helper-hidden-container" style="display:none">
<form id="download-helper-form" target="pdf-download-output" method="post">
<input type="hidden" name="downloadHelperTransferData" id="downloadHelperTransferData" />
</form>
<iframe id="pdf-helper-output" name="pdf-download-output"></iframe>
</div>
Javascript
var form = document.getElementById(''download-helper-form'');
$("#downloadHelperTransferData").val(transferData);
form.action = "ServerSideFunctionWhichWritesPdfBytesToResponse";
form.submit();
Debido a target = "pdf-download-output" , la respuesta se escribe en el iframe y, por lo tanto, no se ejecuta ninguna recarga de página, pero el pdf-response-stream se genera en el navegador como descarga.
crea un iframe escondido, luego en tu código ajax arriba:
url: document.getElementById(''myiframeid'').src = your_server_side_url
,
y elimine window.open(response);
var xhr;
var beforeSend = function(){
$(''#pleasewaitDL'').modal(''show'');
}
$(function () {
$(''#print_brochure_link'').click(function(){
beforeSend();
xhr = new XMLHttpRequest();
xhr.open("GET",$(''#preparedPrintModalForm'').attr(''action''), true);
xhr.responseType = "blob";
xhr.onload = function (e) {
if (this.status === 200) {
var file = window.URL.createObjectURL(this.response);
var a = document.createElement("a");
a.href = file;
a.download = this.response.name || "Property Brochure";
console.log(file);
document.body.appendChild(a);
a.click();
window.onfocus = function () {
document.body.removeChild(a)
}
$(''#pleasewaitDL'').modal(''hide'');
};
};
xhr.send($(''#preparedPrintModalForm'').serialize());
});
$(''#pleasewaitDLCancel'').click(function() {
xhr.abort();
});
});