在获得该文件的响应(成功的ajax方法)后,我在获取Excel文件并在浏览器中打开下载窗口时遇到问题。我有合适的
Content-Type and Content-Disposition headers
,我尝试在js中使用Blob,但无法实现我想要的 - 简单的文件下载。也许问题在于 Blob 构造函数中使用了不适当的数据类型?
我尝试使用成功方法参数中的“xhr.response”而不是“data”,但它也不起作用。我检查了 Chrome 开发者工具中的响应标头,它们设置正确。
重要的是 - 在服务器端创建的所有 Excel 工作簿都是正确的,因为它在以前的版本中工作,当数据在 URL 中发送时,而不是在 ajax post 中。
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);
}
我的 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);
}
看起来 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();
经过多次搜索从 Web API 获取具有 Unicode 内容的 Excel 文件。最后,这段代码对我有用:
$.ajax({
type: 'GET',
cache: false,
url: "https://localhost:44320/WeatherForecast",
xhrFields: {
// make sure the response knows we're expecting a binary type in return.
// this is important, without it the excel file is marked corrupted.
responseType: 'arraybuffer'
}
})
.done(function (data, status, xmlHeaderRequest) {
var downloadLink = document.createElement('a');
var blob = new Blob([data],
{
type: xmlHeaderRequest.getResponseHeader('Content-Type')
});
var url = window.URL || window.webkitURL;
var downloadUrl = url.createObjectURL(blob);
var fileName = '';
if (typeof window.navigator.msSaveBlob !== 'undefined') {
window.navigator.msSaveBlob(blob, fileName);
} else {
if (fileName) {
if (typeof downloadLink.download === 'undefined') {
window.location = downloadUrl;
} else {
downloadLink.href = downloadUrl;
downloadLink.download = fileName;
document.body.appendChild(downloadLink);
downloadLink.click();
}
} else {
window.location = downloadUrl;
}
setTimeout(function () {
url.revokeObjectURL(downloadUrl);
},
100);
}
});
我们最近遇到了完全相同的麻烦。对于我们来说,当我们将
responseType: 'arraybuffer'
添加到 ajax
参数时,它开始起作用。最好使用 lib https://github.com/eligrey/FileSaver.js/
而不是手动点击链接,因为这个工具也会撤销内存。
在我的例子中,这个sinpcode可以正常工作
$('.btnExportToExcel').click(async (e) => {
e.preventDefault();
const info = JSON.parse(e.currentTarget.dataset.info);
let action = 1;
try {
const data = {
idCampagna: info.idCampagna,
fileName: info.fileName,
};
this.ShowSpinner("Downloading");
// this.HideSpinner();
$.ajax({
type: 'GET',
cache: false,
url: "ExportToExcel",
data: data,
xhrFields: {
// make sure the response knows we're expecting a binary type in return.
// this is important, without it the excel file is marked corrupted.
responseType: 'arraybuffer'
}
})
.done(function (data, status, xmlHeaderRequest) {
var downloadLink = document.createElement('a');
var blob = new Blob([data],
{
type: xmlHeaderRequest.getResponseHeader('Content-Type')
});
var url = window.URL || window.webkitURL;
var downloadUrl = url.createObjectURL(blob);
var fileName = '' +'.xls';
if (typeof window.navigator.msSaveBlob !== 'undefined') {
window.navigator.msSaveBlob(blob, fileName);
} else {
if (fileName) {
if (typeof downloadLink.download === 'undefined') {
window.location = downloadUrl;
} else {
downloadLink.href = downloadUrl;
downloadLink.download = fileName;
document.body.appendChild(downloadLink);
downloadLink.click();
}
} else {
window.location = downloadUrl;
}
setTimeout(function () {
url.revokeObjectURL(downloadUrl);
},
100);
}
});
this.HideSpinner();
} catch (error) {
console.log(error);
}
});