我正在尝试对发送JSON数据的服务器进行POST调用。服务器获取JSON数据,进行一些处理,然后发回Excel .xlsx作为响应。我希望浏览器打开“将文件另存为”对话框以供用户保存。我一直在寻找一个干净的解决方案来做到这一点。但是这个问题JavaScript/jQuery to download file via POST with JSON data中的一个可能的解决方案建议将Excel文件保存在服务器上然后发回URL链接,然后打开iframe供用户下载。这对我来说是不行的,因为用户可以在服务器上创建数千个Excel文件,并且服务器具有有限的节省空间。我希望解决方案能够即时实现。我见过的另一个解决方案建议将数据转换为表单,然后使用表单提交。再次这是一个禁忌,因为我的数据在数百甚至数千个Excel行的范围内。
我的jQuery POST调用:
$.ajax({ type: 'POST', url: '/server/path', data: JSON.stringify(dataSent), processData: false, success: function(data, textStatus, jqXHR) { }, error: function(result, status, err) { }, contentType: 'application/json', dataType: 'application/vnd.ms-excel' });
在后端我设置了这个:
Response.header(“Content-Type”,“application / vnd.ms-excel”)
Response.header(“Content-Disposition”,“attachment; filename = \”export.xlsx \“”)
强制浏览器打开“将文件另存为...”对话框的最佳方法是什么?
谢谢,
答案 0 :(得分:0)
我不确定是否有办法通过JS接收二进制数据然后启动下载。
如果我的任务是,我会将方法更改为GET并生成文件(作为流)并使用适当的标头返回它(Content-Disposition,Content-Length,Content-Type)
答案 1 :(得分:0)
我找到了解决这个问题的方法。我没有进行POST调用来强制浏览器打开保存对话框,而是进行POST调用以生成文件,然后将文件临时存储在服务器上,返回文件名。然后使用“Content-Disposition:attachment; filename = filename1”对此文件使用GET调用。使用该标头的GET调用将强制浏览器始终打开“保存此文件”对话框。
答案 2 :(得分:0)
Blob URLs实际上很容易。
首先,下载文件。我会在TypeScript中使用fetch
和async
/ await
(您可以始终使用保证链而不是async
/ await
和/或XHR而不是{ {1}}):
fetch
现在你有了一个blob,你可以通过创建一个Blob URL和一个隐藏的链接将它传递给一个函数来下载它:
(async () => {
let response = await fetch("/post/path", {
body: JSON.stringify(data), // must match 'Content-Type' header
headers: {
'content-type': 'application/json'
},
method: 'POST',
});
let blob = await response.blob();
let filename = "file.txt";
saveBlobAsFile(filename, blob); // This function is defined below
})();
/**
* Downloads a blob as a file.
*
* TODO: Support iOS Safari, which doesn't support the "download" attribute.
*
* @param name The name of the downloaded file
* @param blob The blob to download
*/
export function saveBlobAsFile(name: string, blob: Blob) {
// IE10 & IE11 Support, since they don't support the "download"
// attribute on anchor tags.
if (navigator.msSaveBlob) {
navigator.msSaveBlob(blob, name);
return;
}
// Create the URL and hidden anchor tag
let $hiddenAnchorTag = $('<a style="display: none;"/>');
let url = URL.createObjectURL(blob);
// Set the attributes for the download
$hiddenAnchorTag.attr('href', url);
$hiddenAnchorTag.attr('download', name);
// Insert the link and click to download
$(document.body).append($hiddenAnchorTag);
$hiddenAnchorTag[0].click();
// Clean up after ourselves
$hiddenAnchorTag.remove();
URL.revokeObjectURL(url);
}
响应对象包含标头,因此您可以解析Content-Disposition以获取服务器所需的文件名。我在网上找到了几个很好的正则表达式,对此非常有用。里程可能会有所不同,但我建议为此制作一个功能,并将其与一些不错的单元测试绑定。