Scarica e apri il file PDF usando Ajax

Ho una class di azioni che genera un PDF. Il contentType è impostato in modo appropriato.

 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; } } 

Chiamo questa action attraverso una chiamata Ajax. Non conosco il modo di consegnare questo stream al browser. Ho provato alcune cose ma non ha funzionato.

 $.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)); } }); 

Quanto sopra dà l’errore:

Il tuo browser ha inviato una richiesta che questo server non è riuscito a capire.

Non hai necessariamente bisogno di Ajax per questo. Basta un collegamento se si imposta la content-disposition del content-disposition attachment nel codice lato server. In questo modo la pagina genitore rimarrà aperta, se questa è la tua principale preoccupazione (perché altrimenti dovresti scegliere Ajax per questo altrimenti?). Inoltre, non c’è modo di gestirlo in modo abbastanza sincrono. PDF non è un carattere. Sono dati binari. Non puoi fare cose come $(element).load() . Vuoi usare una richiesta completamente nuova per questo. Per questo pdf è perfettamente adatto.

Per assisterti di più con il codice lato server, dovrai dire di più sulla lingua utilizzata e pubblicare un estratto dei tentativi di codice.

Ecco come ho ottenuto questo lavoro

 $.ajax({ url: '', success: function(data) { var blob=new Blob([data]); var link=document.createElement('a'); link.href=window.URL.createObjectURL(blob); link.download=""; link.click(); } }); 

Non penso davvero che nessuna delle risposte precedenti abbia individuato il problema del poster originale. Presumono tutti una richiesta GET mentre il poster stava tentando di inviare i dati POST e ottenere un download in risposta.

Nel corso della ricerca di una risposta migliore, abbiamo trovato questo plugin jQuery per la richiesta di download di file tipo Ajax .

Nel suo “cuore” crea un modulo HTML temporaneo contenente i dati dati come campi di input. Questo modulo viene aggiunto al documento e inviato all’URL desiderato. Subito dopo il modulo viene rimosso di nuovo:

 jQuery('
'+inputs+'
') .appendTo('body').submit().remove()

Aggiornamento La risposta di Mayur sembra piuttosto promettente e molto semplice rispetto al plug-in jQuery a cui mi riferivo.

Questo è il modo in cui risolvo questo problema.
La risposta di Jonathan Amend su questo post mi ha aiutato molto.
L’esempio di seguito è semplificato.

Per ulteriori dettagli, il codice sorgente sopra è in grado di scaricare un file utilizzando una richiesta Ajax JQuery (GET, POST, PUT, ecc . ) . Inoltre, aiuta a caricare i parametri come JSON e a modificare il tipo di contenuto in application / json (il mio predefinito) .

La fonte html :

 

Un semplice modulo con due testo di input, un elemento di selezione e un pulsante.

L’origine della pagina javascript :

   

Un semplice evento sul pulsante clic. Crea un object AjaxDownloadFile. L’origine della class AjaxDownloadFile è riportata di seguito.

L’ origine della class 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(); } }; 

Ho creato questa class per aggiungerla alla mia libreria JS. È riutilizzabile. Spero possa aiutare.

Potresti usare questo 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 += ''; }); //send request jQuery('
' + inputs + '
') .appendTo('body').submit().remove(); }; }; $.download( '/export.php', 'filename=mySpreadsheet&format=xls&content=' + spreadsheetData );

Questo ha funzionato per me. Trovato questo plugin qui

Ciò che ha funzionato per me è il seguente codice, poiché la funzione server sta recuperando 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(); } }); 

crea un iframe nascosto, quindi nel tuo codice Ajax qui sopra:

url: document.getElementById('myiframeid').src = your_server_side_url ,

e rimuovere window.open(response);

Devi farlo con l’Ajax? Non potrebbe essere una possibilità caricarlo in un iframe?

Questo snippet è per utenti js angolari che dovranno affrontare lo stesso problema. Si noti che il file di risposta viene scaricato utilizzando un evento click programmato. In questo caso, le intestazioni sono state inviate dal server contenente nome file e contenuto / 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 () { }); 

Per quanto riguarda la risposta fornita da Mayur Padshala, questa è la logica corretta per scaricare un file pdf tramite ajax ma, come altri riportano nei commenti, questa soluzione scarica effettivamente un pdf vuoto.

La ragione di ciò è spiegata nella risposta accettata di questa domanda : jQuery ha alcuni problemi nel caricare dati binari usando le richieste AJAX, poiché non implementa ancora alcune funzionalità XHR v2 HTML5, vedi questa richiesta di miglioramento e questa discussione .

Quindi usando HTMLHTTPRequest il codice dovrebbe assomigliare a questo:

 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(); } 
 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(); }); }); 

Se devi lavorare con file-stream (quindi nessun PDF salvato fisicamente) come facciamo noi e vuoi scaricare il PDF senza ricaricare la pagina, la seguente funzione funziona per noi:

HTML

  

Javascript

 var form = document.getElementById('download-helper-form'); $("#downloadHelperTransferData").val(transferData); form.action = "ServerSideFunctionWhichWritesPdfBytesToResponse"; form.submit(); 

A causa dell’objective = “pdf-download-output” , la risposta viene scritta nell’iframe e quindi non viene eseguito il ricaricamento della pagina, ma il stream della risposta pdf viene emesso nel browser come download.