Javascript 从ajax中的服务器响应中获取excel文件(.xlsx)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/47134698/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get excel file (.xlsx) from server response in ajax
提问by KamilosD
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 Blobin 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 文件并在浏览器中打开下载窗口时遇到问题。我有合适的Content-Type and Content-Disposition headers,我尝试在 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.response”而不是来自成功方法参数的“数据”,但它也不起作用。我在 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]*=((['"]).*?|[^;\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);
}
回答by KamilosD
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();
回答by Aleksandra Vetrova
We were having absolutely the same trouble recently. For us it started to work when we add responseType: 'arraybuffer'to the ajaxparameters. 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.
我们最近遇到了完全相同的麻烦。对我们来说,当我们添加参数时它就开始工作responseType: 'arraybuffer'了ajax。最好使用 libhttps://github.com/eligrey/FileSaver.js/而不是手动单击链接,因为该工具也会撤销内存。

