在我的ember.js
网络应用中,用户可以选择下载一个zip文件。单击该按钮时,将触发一个操作,该操作将请求发送到后端服务器,该服务器生成zip并将其返回。理想情况下,应该自动下载zip。
在我的后端端点中,我返回
return Response
.ok(FileUtils.readFileToByteArray(new File(tmpZipFilename))) // tmpZipFilename is a String
.type("application/zip")
.header("Content-Disposition", "attachment; filename=\"" + finalZipFilename + "\"")
.build();
我在前端(改编自here)
submit() {
var formData = new FormData(this);
let token = this.get('session.data.authenticated.token');
jquery.ajax({
url: `myUrl`,
data: formData,
processData: false,
contentType: false,
beforeSend: function(xhr) {xhr.setRequestHeader('Authorization', `Bearer ${token}`)},
type: 'POST',
success: function(data) {
var blob = new Blob([data], {type: 'application/zip'});
let a = document.createElement("a");
a.style = "display: none";
document.body.appendChild(a);
let url = window.URL.createObjectURL(blob);
a.href = url;
a.download = 'myFile.zip';
a.click();
window.URL.revokeObjectURL(url);
},
failure: function() {
// other stuff
}
})
}
响应头如下:
HTTP/1.1 200 OK
X-Powered-By: Undertow/1
Cache-Control: no-store
Date: Tue, 19 Feb 2019 16:34:35 GMT
Server: WildFly/10
Content-Type: application/zip
Content-Disposition: attachment; filename="filename.zip"
Connection: close
Transfer-Encoding: chunked
我已经确认后端部分中的tmpZipFilename
确实指向正确的zip文件。而且,当用户单击下载按钮时,确实下载了名为myFile.zip
的文件。但是,下载的文件不可解压缩,并且大小与tmpZipFilename
所指向的正确文件不同。我在做什么错了?
答案 0 :(得分:1)
答案是简单地添加dataType: 'arraybuffer'
:
...
jquery.ajax({
url: 'myUrl',
data: formData,
processData: false,
contentType: false,
dataType: 'arraybuffer',
beforeSend: function(xhr) {
...
答案 1 :(得分:0)
实际上,下载文件的最佳解决方案是只调用window.open
。
答案 2 :(得分:0)
如果您的API返回的是实际文件,并且您正确设置了内容类型和处理方式,则只需在前端创建一个指向api端点的自然链接,或者使用标准格式而不是AJAX请求即可,文件下载将触发,就寡妇而言,您将留在同一地方。
对于选项一:
<a href="<API_ENDPOINT>?token=<token>¶m1=something¶m2=something">download</a>
这可以通过将参数绑定到url字符串来工作。但是,我建议您不要使用此方法,除非您有办法创建签名的单次使用获取身份验证令牌,因为您永远都不应在任何可读的位置发送访问令牌。
选项2是创建一个通用HTML表单,其中的操作是api端点,您可以在其中将标记传递到发布数据中。如果您的API端点简单返回了一个正确的文件,则在提交表单后,应下载该文件,并且您应该能够停留在同一页面上。
<form action="<API ENDPOINT>" method="post">
<!-- Standard input types named appropriately
</form>
这些只是几个解决方案。我个人喜欢选项1,但前提是您可以安全地使用它。如果您可以在后端存储和管理某种随机数,请研究HMAC身份验证方法以创建此一次性令牌。与JWT配合良好。