File retrieval from AWS S3 to Node.js server, and then to React client

Viewed 1913

I have a need to retrieve individual files from Node.js with Express.js. For that, I have installed aws-sdk, as well as @aws-sdk/client-s3. I am able to successfully fetch the file by using this simple endpoint:

const app = express(),
      { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3'),
      s3 = new S3Client({ region: process.env.AWS_REGION });

app.get('/file/:filePath', async (req,res) => {
  const path_to_file = req.params.filePath;

  try {
    const data = await s3.send(new GetObjectCommand({ Bucket: process.env.AWS_BUCKET, Key: path_to_file }));
    console.log("Success", data);
  } catch (err) {
    console.log("Error", err);
  }
});

...but I have no idea how to return the data correctly to the React.js frontend so that the file can be further downloaded. I tried to look up the documentation, but it's looking too messy for me, and I can't even get what does the function return. .toString() method didn't help because it simply returns `"[object Object]" and nothing really else.

On React, I am using a library file-saver, which works with blobs and provides them for download using a filename defined by user.

Node v15.8.0, React v16.4.0, @aws-sdk/client-s3 v3.9.0, file-saver v2.0.5

Thanks for your tips and advices! Any help is highly appreciated.

2 Answers

Generally data from S3 is returned as a buffer. The file contents are part of the Body param in the response. You might be doing toString on the root object.

You need to use .toString() on the body param to make it a string.

Here is some sample code that might work for use case

// Note: I am not using a different style of import
const AWS = require("aws-sdk")
const s3 = new AWS.S3()

const Bucket = "my-bucket"

async getObject(key){
 const data = await s3.getObject({ Bucket, key}).promise()
 if (data.Body) {return data.Body.toString("utf-8") } else { return undefined}
}

To return this in express, you can add this to your route and pass the final data back once you have it.

res.end(data));

Consuming it in React should be the same as taking values from any other REST API.

I used Ravi's answer but caused a problem to display the image object in Frontend.

this worked fine:

  const data = await s3.send(new GetObjectCommand({ Bucket: process.env.AWS_BUCKET, Key: path_to_file }));
  data.Body.pipe(res);
Related