I have got a problem with getting excel file and opening download window in the browser after getting a response (in success ajax method) with that file. I have got appropriate Content-Type and Content-Disposition headers
, I tried using Blob in js and I couldn't achieve what I want - simple file downloading.
I accomplished few versions of my ajax, one of them is below. I developed ajax which returns excel file which I couldn't open properly because it's corrupted (despite .xlsx extension).
在获得了该文件的响应(成功ajax方法)之后,我在浏览器中获得了excel文件和打开下载窗口的问题。我有适当的内容类型和内容配置头,我尝试在js中使用Blob,但我无法实现我想要的——简单的文件下载。我完成了ajax的几个版本,其中一个在下面。我开发了ajax,它返回excel文件,我无法正确打开该文件,因为它已被损坏(尽管有.xlsx扩展名)。
Maybe the problem is with inappropriate data type used in Blob constructor?
可能问题是Blob构造函数中使用了不合适的数据类型?
I tried using "xhr.response" instead of "data" from success method arguments but it doesn't work too. I checked Response Headers in Developer Tools in Chrome and they are set properly.
The important thing - all the excel workbooks created on the server side is correct because it worked in the previous version when data was sent in URL, not in ajax post.
我试着使用“xhr。响应“而不是成功方法参数的“数据”,但它也不起作用。我在Chrome中检查了开发者工具的响应头,它们被正确设置。重要的是,在服务器端创建的所有excel工作簿都是正确的,因为在以前的版本中,数据是在URL中发送的,而不是在ajax post中。
Controller method in Java/Spring server side below:
Java/Spring服务器端控制器方法:
response.reset();
response.setContentType("application/vnd.ms-excel");
response.addHeader("Content-Disposition","attachment;filename=\"" + className + " " + title + ".xlsx\"");
try (ServletOutputStream output = response.getOutputStream()){
workbook.write(output);
output.flush();
} catch (Exception e) {
throw new RuntimeException(e);
}
My Ajax to download file and open download window:
我的Ajax下载文件和打开下载窗口:
$.ajax({
url: myUrl,
type: 'POST',
data: myData,
success: function(data, status, xhr) {
var contentType = 'application/vnd.ms-excel';
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, '');
}
console.log("FILENAME: " + filename);
try {
var blob = new Blob([data], { type: contentType });
var downloadUrl = URL.createObjectURL(blob);
var a = document.createElement("a");
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
} catch (exc) {
console.log("Save Blob method failed with the following exception.");
console.log(exc);
}
2 个解决方案
#1
2
It looks like JQuery have got some problem with dealing with the binary data from the response. I used simply XMLHttpRequest and I add all data to the URL.
看起来JQuery在处理来自响应的二进制数据时遇到了一些问题。我只使用了XMLHttpRequest,并将所有数据添加到URL。
var request = new XMLHttpRequest();
request.open('POST', url, true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.responseType = 'blob';
request.onload = function(e) {
if (this.status === 200) {
var blob = this.response;
if(window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveBlob(blob, fileName);
}
else{
var downloadLink = window.document.createElement('a');
var contentTypeHeader = request.getResponseHeader("Content-Type");
downloadLink.href = window.URL.createObjectURL(new Blob([blob], { type: contentTypeHeader }));
downloadLink.download = fileName;
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
}
}
};
request.send();
#2
0
We were having absolutely the same trouble recently. For us it started to work when we add responseType: 'arraybuffer'
to the ajax
parameters. And it's better to use lib https://github.com/eligrey/FileSaver.js/
instead of manual clicking on the link because this tool revokes memory as well.
最近我们遇到了同样的麻烦。对于我们来说,当我们向ajax参数添加responseType: 'arraybuffer'时,它就开始工作了。最好使用lib https://github.com/eligrey/FileSaver.js/而不是手动点击链接,因为这个工具也会撤销内存。
#1
2
It looks like JQuery have got some problem with dealing with the binary data from the response. I used simply XMLHttpRequest and I add all data to the URL.
看起来JQuery在处理来自响应的二进制数据时遇到了一些问题。我只使用了XMLHttpRequest,并将所有数据添加到URL。
var request = new XMLHttpRequest();
request.open('POST', url, true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.responseType = 'blob';
request.onload = function(e) {
if (this.status === 200) {
var blob = this.response;
if(window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveBlob(blob, fileName);
}
else{
var downloadLink = window.document.createElement('a');
var contentTypeHeader = request.getResponseHeader("Content-Type");
downloadLink.href = window.URL.createObjectURL(new Blob([blob], { type: contentTypeHeader }));
downloadLink.download = fileName;
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
}
}
};
request.send();
#2
0
We were having absolutely the same trouble recently. For us it started to work when we add responseType: 'arraybuffer'
to the ajax
parameters. And it's better to use lib https://github.com/eligrey/FileSaver.js/
instead of manual clicking on the link because this tool revokes memory as well.
最近我们遇到了同样的麻烦。对于我们来说,当我们向ajax参数添加responseType: 'arraybuffer'时,它就开始工作了。最好使用lib https://github.com/eligrey/FileSaver.js/而不是手动点击链接,因为这个工具也会撤销内存。