简体   繁体   English

尝试从后端向前端发送 zip

[英]Trying to send a zip from the backend to the frontend

At one point in my ember.js webapp the user is given the option to download a zip file.在我的ember.js webapp 中,用户可以选择下载 zip 文件。 On clicking the button, an action is triggered that sends a request to the backend server, which generates the zip and returns it.单击按钮时,会触发一个操作,向后端服务器发送请求,后端服务器生成 zip 并将其返回。 Ideally the zip should then be downloaded automatically.理想情况下,zip 应该会自动下载。

In my backend endpoint I return with在我的后端端点中,我返回

return Response
        .ok(FileUtils.readFileToByteArray(new File(tmpZipFilename))) // tmpZipFilename is a String
        .type("application/zip")
        .header("Content-Disposition", "attachment; filename=\"" + finalZipFilename + "\"")
        .build();

In the frontend I have (adapted from here )在前端我有(改编自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
    }
  })
}

The response headers are the following:响应头如下:

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

I have confirmed that tmpZipFilename in the backend section does correctly point to a proper zip file.我已经确认后端部分中的tmpZipFilename确实正确指向了正确的 zip 文件。 And when the user clicks the download button a file called myFile.zip is indeed downloaded.当用户单击下载按钮时,确实下载了名为myFile.zip的文件。 However, the file downloaded is not unzippable and is a different size than the correct file pointed to by tmpZipFilename .但是,下载的文件不可解压缩,并且与tmpZipFilename指向的正确文件的大小不同。 What am I doing wrong?我究竟做错了什么?

The answer was to simply add dataType: 'arraybuffer' :答案是简单地添加dataType: 'arraybuffer'

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

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

IF your API is returning an actual file, and you have the content type and disposition set correctly, you can just create a natural link in the frontend to the api endpoint, or use a standard form and not an AJAX request, as the file download will trigger and you will stay in the same place as far as the widow is concerned.如果您的 API 返回的是实际文件,并且您正确设置了内容类型和配置,则可以在前端创建一个自然链接到 api 端点,或者使用标准表单而不是 AJAX 请求作为文件下载将触发,而就寡妇而言,您将留在同一个地方。

For option one:对于选项一:

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

This can work by binding the parameters to the url string.这可以通过将参数绑定到 url 字符串来实现。 However I would advise against this method unless you have a way to create SIGNED SINGLE USE GET AUTHENTICATION TOKENS as you should never be sending access tokens anywhere readable.但是,我建议不要使用这种方法,除非您有办法创建SIGNED SINGLE USE GET AUTHENTICATION TOKENS,因为您永远不应该在任何可读的地方发送访问令牌。

Option 2 is to create a generic HTML form where the action is the api endpoint, where you can pass the token in post data.选项 2 是创建一个通用的 HTML 表单,其中 action 是 api 端点,您可以在其中传递 post 数据中的令牌。 If you API endpoint simple returns a proper file, when the form is submitted the file should download, and you should be able to stay on the same page.如果您的 API 端点简单返回正确的文件,则提交表单时应该下载该文件,并且您应该能够停留在同一页面上。

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

These are just a couple of solutions.这些只是几个解决方案。 I personally like option 1 but only if you can get it working securely.我个人喜欢选项 1,但前提是你可以让它安全地工作。 Research HMAC auth methods to create this single use token if you can store and manage a nonce of some kind on the back end.如果您可以在后端存储和管理某种随机数,请研究 HMAC 身份验证方法来创建此一次性令牌。 Works well with JWTs.与 JWT 配合良好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 试图从后端到前端获取API数据 - Trying to get API data from backend to frontend 将SailsJS后端的zip文件传输到React Redux前端 - Piping zip file from SailsJS backend to React Redux Frontend 当我尝试从我的前端(React-Native/Mongoose)的后路由器发送一组 ObjectID 时,我的后端出错 - Error in my backend when I'm trying to send an array of ObjectID from a post router from my frontend (React-Native/Mongoose) 从后端(Java / Jersey / REST)将数据发送到前端(Angular JS) - Send data to Frontend(Angular JS) from backend (Java/Jersey/REST) 在Sails.js中将值从后端发送到前端,并使用EJS进行检查 - Send value from backend to frontend in Sails.js and check with EJS 如何将数据从html(Django后端)发送到js(Vue前端) - How to send data from html (Django backend) to js (Vue frontend) 通常无法将图像从前端发送到云端或后端 - Unable to send image from frontend to cloudinary or the backend in general 如何安全地从后端发送图像以显示在前端 HTML? - How to securely send image from backend to be displayed in frontend HTML? 如何从前端向后端快速发送数据(url 字符串)? - How to send data (a url string) in express to backend from frontend? 如何在节点中将多个查询结果从后端发送到前端 - How to send multiple query results from backend to frontend in node
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM