Jose A. Ayllón
Jose A. Ayllón

Reputation: 886

NodeJS download file from AWS S3 Bucket

I'm trying to make an endpoint in NodeJS/Express for downloading content from my AWS S3 Bucket.

It works well, I can download the file in the client side but I can also see the stream preview in the Network tab which is annoying...

QUESTION

I'm wondering if what I'm doing is correct and a good practice. Also would like to know if it's normal to see the output stream in the Network tab.

How should I properly send I file from S3 to my client application using NodeJS/Express?

I'm pretty sure other websites requests don't let you preview the content with a: "Fail to load response data".


This is what I do in my NodeJS application to get the stream file from 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);
}

And in the client side I can see this:

enter image description here

Upvotes: 7

Views: 9475

Answers (1)

StefaDesign
StefaDesign

Reputation: 959

I think the issue is with the header :

          //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);

So code should be like this (This is what I am doing it in my project handling file as res.attachment or res.json in case of error so client can display error to end user) :

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);
        }
      });
    });

Upvotes: 4

Related Questions