试图从后端发送拉链到前端

问题描述 投票:1回答:3

在我的ember.js webapp中,用户可以选择下载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指向的正确文件大小不同。我究竟做错了什么?

javascript java jquery ajax ember.js
3个回答
1
投票

答案是简单地添加dataType: 'arraybuffer'

...
jquery.ajax({
    url: 'myUrl',
    data: formData,
    processData: false,
    contentType: false,
    dataType: 'arraybuffer',
    beforeSend: function(xhr) {
...

0
投票

实际上下载文件最好的解决方案就是调用window.open


0
投票

如果您的API返回一个实际文件,并且您正确设置了内容类型和处置,您可以在api端点的前端创建一个自然链接,或者使用标准表单而不是AJAX请求,作为文件下载会触发,就寡妇而言,你会留在同一个地方。

对于选项一:

<a href="<API_ENDPOINT>?token=<token>&param1=something&param2=something">download</a>

这可以通过将参数绑定到url字符串来实现。但是我建议不要使用这种方法,除非你有办法创建SIGNED SINGLE USE GET AUTHENTICATION TOKENS,因为你永远不应该在任何地方可读地发送访问令牌。

选项2是创建一个通用的HTML表单,其中操作是api端点,您可以在后面的数据中传递令牌。如果API端点简单返回正确的文件,则在提交表单时应该下载文件,并且您应该能够保持在同一页面上。

<form action="<API ENDPOINT>" method="post">
  <!-- Standard input types named appropriately
</form>

这些只是几个解决方案。我个人喜欢选项1,但前提是你能安全地工作。如果您可以在后端存储和管理某种类型的随机数,请研究HMAC auth方法来创建此单一用途令牌。适用于JWT。

© www.soinside.com 2019 - 2024. All rights reserved.