【问题标题】:NodeJS download file from AWS S3 Bucket从 AWS S3 存储桶下载 NodeJS 文件
【发布时间】:2019-09-06 09:38:33
【问题描述】:

我正在尝试在 NodeJS/Express 中创建一个端点,用于从我的 AWS S3 存储桶下载内容。

效果很好,我可以在客户端下载文件,但我也可以在“网络”选项卡中看到流预览,这很烦人......

问题

我想知道我所做的是否正确和良好的做法。 也想知道在Network tab看到输出流是否正常。

我应该如何使用 NodeJS/Express 正确地将我的文件从 S3 发送到我的客户端应用程序?

我很确定其他网站请求不会让您预览内容并带有:“无法加载响应数据”。


这是我在 NodeJS 应用程序中从 AWS S3 获取流文件的操作:

download(fileId) {
  const fileObjectStream = app.s3
    .getObject({
      Key: fileId
    })
    .createReadStream();
  this.res.set("Content-Type", "application/octet-stream");
  this.res.set(
    "Content-Disposition",
    'attachment; filename="' + fileId + '"'
  );
  fileObjectStream.pipe(this.res);
}

在客户端我可以看到:

【问题讨论】:

  • 我想另一种选择是让 nodejs 创建一个签名的 url 并将其发送给客户端。然后客户端可以使用该签名的 url 访问 S3 内容

标签: javascript node.js amazon-web-services express amazon-s3


【解决方案1】:

我认为问题出在标题上:

          //this line will set proper header for file and make it downloadable in client's browser

          res.attachment(key); 

          // this will execute download 
          s3.getObject(bucketParams)
          .createReadStream()
          .pipe(res);

所以代码应该是这样的(这是我在我的项目处理文件中作为 res.attachment 或 res.json 执行的操作,以防出错,以便客户端可以向最终用户显示错误):

router.route("/downloadFile").get((req, res) => {
      const query = req.query; //param from client
      const key = query.key;//param from client
      const bucketName = query.bucket//param from client

      var bucketParams = {
        Bucket: bucketName,  
        Key: key
      };

      //I assume you are using AWS SDK
      s3 = new AWS.S3({ apiVersion: "2006-03-01" });

      s3.getObject(bucketParams, function(err, data) {
        if (err) {
          // cannot get file, err = AWS error response, 
          // return json to client
          return res.json({
            success: false,
            error: err
          });
        } else {
          res.attachment(key); //sets correct header (fixes your issue ) 
          //if all is fine, bucket and file exist, it will return file to client
          s3.getObject(bucketParams)
            .createReadStream()
            .pipe(res);
        }
      });
    });

【讨论】:

  • 这如何触发客户端的下载?
  • 在客户端,正确的标题是触发文件的原因。在常规的 HTTP 响应中,Content-Disposition 响应标头是一个标头,它指示内容是否希望在浏览器中内联显示,即作为网页或网页的一部分,或作为附件,下载并保存在本地。例如 Content-Disposition:附件; filename="whateverIfFileName.jpg" 将向浏览器发送指示以下载文件....在我上面的代码中 res.attachment(key) 是设置正确的文件头的内容,以便浏览器可以下载文件。我希望这会有所帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-04
  • 1970-01-01
  • 2017-10-19
  • 2019-02-16
  • 2021-05-23
  • 1970-01-01
  • 2015-05-20
相关资源
最近更新 更多