【问题标题】:Trying to send a zip from the backend to the frontend试图从后端发送一个 zip 到前端
【发布时间】:2019-02-19 16:53:15
【问题描述】:

在我的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 指向的正确文件的大小不同。我做错了什么?

【问题讨论】:

  • 您没有正确连接这些字符串。 "附件;文件名=\"" + finalZipFilename + "\""
  • 你能用文本编辑器看一下 zip 文件吗?可能是服务器出错的html文件。
  • 看起来像二进制数据,有很多s
  • 我在文本编辑器视图上运行了一个比较好的和坏的拉链。它们几乎相同,只是坏 zip 中的每一行都缺少一些随机的s

标签: javascript java jquery ajax ember.js


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    其实下载文件最好的办法就是拨打window.open

    【讨论】:

      【解决方案3】:

      如果您的 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 端点,您可以在其中传递 post 数据中的令牌。如果您的 API 端点简单返回一个正确的文件,则在提交表单时应该下载该文件,并且您应该能够留在同一页面上。

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

      这些只是几个解决方案。我个人喜欢选项 1,但前提是你可以让它安全地工作。如果您可以在后端存储和管理某种随机数,请研究 HMAC 身份验证方法以创建此一次性令牌。适用于 JWT。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-28
        • 1970-01-01
        • 2018-11-02
        • 2021-07-08
        相关资源
        最近更新 更多