我正在尝试实现这些看似简单的要求但却无法找到方法:
问题主要是,如何将JSON作为请求体传递?最常见的技术似乎是隐藏的HTML表单来触发下载,但HTML表单无法在正文中发送JSON数据。而且我找不到任何方法来使用XMLHttpRequest来触发下载对话框...
有什么想法吗?
我指定了Angular,但任何通用的JS解决方案也非常受欢迎!
答案 0 :(得分:0)
我终于找到了一个满足我所有要求的解决方案,并且可以在IE11,FF和Chrome中运行(并且降低了Safari中的确定......)。
我们的想法是创建一个包含响应数据的Blob
对象,然后强制浏览器将其作为文件打开。 IE(专有API)和Chrome / FF(使用链接元素)略有不同。
这是一个实现,作为一个小的Angular服务:
myApp.factory('Download', [function() {
return {
openAsFile : function(response){
// parse content type header
var contentTypeStr = response.headers('Content-Type');
var tokens = contentTypeStr.split('/');
var subtype = tokens[1].split(';')[0];
var contentType = {
type : tokens[0],
subtype : subtype
};
// parse content disposition header, attempt to get file name
var contentDispStr = response.headers('Content-Disposition');
var proposedFileName = contentDispStr ? contentDispStr.split('"')[1] : 'data.'+contentType.subtype;
// build blob containing response data
var blob = new Blob([response.data], {type : contentTypeStr});
if (typeof window.navigator.msSaveBlob !== 'undefined'){
// IE : use proprietary API
window.navigator.msSaveBlob(blob, proposedFileName);
}else{
var downloadUrl = URL.createObjectURL(blob);
// build and open link - 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.open(downloadUrl);
}
var link = document.createElement('a');
link.href = downloadUrl;
link.download = proposedFileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
}
}]);
response参数需要一个$http
响应对象。以下是使用POST请求的示例:
$http.post(url, {property : 'value'}, {responseType: 'blob'}).then(function(response){
Download.openAsFile(response);
});
请注意responseType
参数。没有这个,我的CSV数据被作为文本读取并以UTF-8(或16)存储在内存中,随后文件以相同的编码保存,导致Excel无法识别特殊字符,如éè等。因为我的CSVs旨在由Excel打开,服务器将它们编码为Windows 1252,我想保持这种方式。将responseType
参数设置为blob
即可实现此目的。
免责声明:它适用于任何文件类型。但我只用CSV文件测试过它!二进制文件的行为可能会有所不同!