使用 REST 从 Amazon S3 下载文件 API

Download file from Amazon S3 using REST API

我有自己的 REST API 可以调用,以便 下载 文件。 (最后,文件可以存储在不同类型的服务器中...Amazon s3,本地等...)

要从 s3 获取文件,我应该使用这种方法:

var url = s3.getSignedUrl('getObject', params);

这会给我一个可下载的 link 来调用。

现在,我的问题是,当文件来自 link 时,我如何使用自己的休息 API 下载文件?有没有办法重定向呼叫?

我正在为我的 REST 服务器使用 Hapi

{
    method: "GET", path: "/downloadFile",
    config: {auth: false},
    handler: function (request, reply) {
        // TODO
        reply({})
    }
},

Return HTTP 303 重定向,Location header 设置为 S3 存储桶中 blob 的 public URL。

如果您的存储桶是私有的,那么您需要代理请求而不是执行重定向,除非您的客户也可以访问该存储桶。

不是使用重定向来下载所需的文件,而是 return 从 S3 返回一个 unbufferedStream。 unbufferedStream 可以从 AWS-SDK 中的 HttpResponse 编辑 return。这意味着不需要从 S3 下载文件,然后读入,然后让请求者下载文件。

仅供参考,我在 Express 中使用了这种 getObject() 方法并且从未使用过 Hapi,但是我认为我与路由定义非常接近,但希望它能抓住我正在尝试的本质实现。

Hapi.js路线

const getObject = require('./getObject');

{
    method: "GET", path: "/downloadFile",
    config: {auth: false},
    handler: function (request, reply) {
        let key = ''; // get key from request
        let bucket = ''; // get bucket from request

        return getObject(bucket, key)
          .then((response) => {
            reply.statusCode(response.statusCode);

            response.headers.forEach((header) => {
              reply.header(header, response.headers[header]);
            });

            return reply(response.readStream);
          })
          .catch((err) => {
            // handle err
            reply.statusCode(500);
            return reply('error');
          });
    }
},

getObject.js

const AWS = require('aws-sdk');
const S3 = new AWS.S3(<your-S3-config>);

module.exports = function getObject(bucket, key) {
  return new Promise((resolve, reject) => {
    // Get the file from the bucket
    S3.getObject({
      Bucket: bucket,
      Key: key
    })
      .on('error', (err) => {            
        return reject(err);
      })
      .on('httpHeaders', (statusCode, headers, response) => {
        // If the Key was found inside Bucket, prepare a response object
        if (statusCode === 200) {
          let responseObject = {
            statusCode: statusCode,
            headers: {
              'Content-Disposition': 'attachment; filename=' + key
            }
          };

          if (headers['content-type'])
            responseObject.headers['Content-Type'] = headers['content-type'];
          if (headers['content-length'])
            responseObject.headers['Content-Length'] = headers['content-length'];

          responseObject.readStream = response.httpResponse.createUnbufferedStream();
          return resolve(responseObject);
        }
      })
      .send();
  });
}