使用Ajax下载并打开pdf文件

我有一个生成pdf的操作类。 contentType被适当设置。

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

我通过Ajax调用来调用这个action 。 我不知道如何将这个stream传递给浏览器。 我尝试了一些东西,但没有任何工作。

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

以上给出了错误:

您的浏览器发送了此服务器无法理解的请求。

你不一定需要这个Ajax。 如果在服务器端代码中将content-dispositionattachment ,那么只需<a>链接即可。 这样父页面将保持打开状态,如果这是您主要关心的问题(为什么您不必要地为此select了Ajax?)。 另外,没有办法很好地处理这个asynchronous。 PDF不是字符数据。 这是二进制数据。 你不能做像$(element).load()这样的东西。 你想要使用全新的请求。 对于这个<a href="pdfservlet/filename.pdf">pdf</a>是完全合适的。

为了帮助您更好地使用服务器端代码,您需要详细讲述所使用的语言,并张贴代码尝试的摘录。

这是我如何得到这个工作

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

我并不认为过去的答案都能找出原来的海报问题。 他们都假定一个GET请求,而海报试图发布数据,并获得响应的下载。

在寻找更好的答案的过程中,我们发现这个jQuery插件用于请求类似Ajax的文件下载 。

在它的“心脏”中,它创build一个包含给定数据的“临时”HTML表单作为input字段。 这种forms被附加到文档并张贴到所需的URL。 在此之后,表单又被删除:

 jQuery('<form action="'+ url +'" method="'+ (method||'post') +'">'+inputs+'</form>') .appendTo('body').submit().remove() 

更新 Mayur的答案看起来相当有前途,与我提到的jQuery插件相比非常简单。

这是我如何解决这个问题。
Jonathan Amend对这个post的回答帮了我很多。
下面的例子被简化了。

有关更多详细信息,上述源代码可以使用JQuery Ajax请求(GET,POST,PUT等)下载文件 。 它也有助于将参数上载为JSON并将内容types更改为application / json(我的默认值)

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> 

两个input文本,一个select和一个button元素的简单forms。

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> 

一个简单的事件点击button。 它创build一个AjaxDownloadFile对象。 下面是AjaxDownloadFile类的来源。

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

我创build了这个类来添加到我的JS库。 它是可重用的。 希望有所帮助。

你可以使用这个插件。

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

这对我有效。 在这里find这个插件

以下代码适用于我,因为服务器函数正在检索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(); } }); 

创build一个隐藏的iframe,然后在你的ajax代码上面:

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

并删除window.open(response);

你需要使用Ajax吗? 不可能把它加载到iframe中吗?

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

如果您必须像使用文件stream一样使用文件stream(因此不需要保存PDF),并且您不想下载PDF而无需重新加载页面,以下function适用于我们:

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

由于target =“pdf-download-output” ,响应被写入iframe中,因此不执行页面重新加载,但是pdf-响应stream在浏览器中作为下载被输出。