Download file from Amazon S3 using REST API

后端 未结 2 822
说谎
说谎 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();
    
    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();
      });
    }
    

提交回复
热议问题