7

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

Jose A. Ayllón
  • 866
  • 6
  • 19
  • 3
    I guess another option is to have nodejs create a signed url and send that to the client instead. The client can then use that signed url to access the S3 content – dbramwell Apr 16 '19 at 10:29

1 Answers1

4

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);
        }
      });
    });
StefaDesign
  • 929
  • 10
  • 19
  • How does this trigger the download on the client side tho? – insivika May 26 '20 at 18:37
  • Well on client side proper header is what triggers file. In a regular HTTP response, the Content-Disposition response header is a header indicating if the content is expected to be displayed inline in the browser, that is, as a Web page or as part of a Web page, or as an attachment, that is downloaded and saved locally. For example Content-Disposition: attachment; filename="whateverIfFileName.jpg" will send to browser indication to download file.... In my code above res.attachment(key) is what sets up the correct file header so file can be downloaded by browser. I hope this helps. – StefaDesign Jun 30 '20 at 23:01
  • when i try to download, the download speed is very slow. What could be the reason? – prince david Nov 07 '22 at 15:12
  • It really can be various set of events that can cause slowness. Some I can think off, are slow or unstable connection (usually internet connection on your end). That can be the main reason as well as file size (logically depends on what you are downloading video ,image or txt file). Another thing I can think of would be how your machine (computer) is set up in your network before you reach out S3 (tunnels, vpn, proxies etc) maybe traffic from your machine to S3 has indirect route which might cause some speed issues. – StefaDesign Nov 08 '22 at 17:32