Download file from Amazon S3 using REST API

后端 未结 2 820
说谎
说谎 2021-02-10 09:21

I have my own REST API to call in order to download a file. (At the end, the file could be store in different kind of server... Amazon s3, loca

相关标签:
2条回答
  • 2021-02-10 10:14

    Instead of using a redirect to download the desired file, just return back an unbufferedStream instead from S3. An unbufferedStream can be returned from the HttpResponse within the AWS-SDK. This means there is no need to download the file from S3, then read it in, and then have the requester download the file.

    FYI I use this getObject() approach with Express and have never used Hapi, however I think that I'm pretty close with the route definition but hopefully it will capture the essence of what I'm trying to achieve.

    Hapi.js route

    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();
      });
    }
    
    0 讨论(0)
  • 2021-02-10 10:16

    Return a HTTP 303 Redirect with the Location header set to the blob's public URL in the S3 bucket.

    If your bucket is private then you need to proxy the request instead of performing a redirect, unless your clients also have access to the bucket.

    0 讨论(0)
提交回复
热议问题