2

I am trying to access the AWS S3 signed URL using a wrapper API created in Node JS and Express.

I am redirecting an url to call the Node API using nginx. In Node API I am setting the 'Content-Type' response headers according to the file type being returned by S3 URL before returning the repsonse from Node API.

When I access the URL to fetch the document in S3 via wrapper Node API I am not getting any content. In case of PDF files I am getting blank white screen.

Below is the block of code I am using to fetch the document from S3 in Node wrapper API and relay the same response.

const request = require('request');

request(s3SignedURL, function (error, result, body) {
    if (!error) {
        res.header('Content-Type','application/pdf');
        res.end(body);
    } else {
        res.status(500).send(error);
    }
});

[EDIT]

I am storing the details of file uploaded S3 in an table and using that table to fetch the document when someone tries to access it. Below is the complete code used.

const S3 = new AWS.S3();

app.get("/getFile/*", function (req, res) {
    var urlInfo = req.url;
    var urlInfoList = urlInfo.split("/");
    var accessCode = urlInfoList[2];
    var accessID = urlInfoList[3];

    if (!!accessID && !!accessCode) {
        db.getFileInfo(accessCode, accessID).then(function (fileInfo) {
            if (fileInfo.length > 0) {
                var S3Options = {
                    Bucket: Bucketname,
                    Key: fileInfo[0].fileS3Key,
                };
                S3.getObject(S3Options, function (err, data) {
                    res.attachment(fileInfo[0].fileS3Key);
                    res.send(data.Body);
                });

                // request(fileInfo[0].fileS3URL).pipe(res.set('Content-Type', 'application/pdf').set('Content-Disposition', 'inline'));
            } else {
                res.status(404).send("<html><head><title>404 Not Found</title></head><body bgcolor=\"white\"><center><h1>404 Not Found</h1></center><hr></body></html>");
            }
        }, function (fileErr) {
            console.log('fileErr');
            console.log(fileErr);
            res.status(404).send("<html><head><title>404 Not Found</title></head><body bgcolor=\"white\"><center><h1>404 Not Found</h1></center><hr></body></html>");
        });
    } else {
        res.status(404).send("<html><head><title>404 Not Found</title></head><body bgcolor=\"white\"><center><h1>404 Not Found</h1></center><hr></body></html>");
    }
});

Any help in this regard will be very useful.

2 Answers 2

2

You are getting a blank screen because you need to send the Content-Disposition parameter as well.

By the way, the purpose of the pre-signed url is to get temporary access to s3 objects from environments that are publicly exposed (outside AWS environment) . You don't have to use pre-signed URL mechanism from a backend service where you can access the object securely via SDK

const express = require('express');
const app = express();
const request = require('request');

app.get('/download-file', function (req, res) {

  // sdk way
  var s3 = new AWS.S3({});
  var options = {
    Bucket: 'my-bucket-name',
    Key: file,
  };
  s3.getObject(options, function (err, data) {
    res.setHeader('Content-disposition', `inline; filename="${filename}"`);
    res.end(data.Body, 'binary');
  });

  // http way
  request('https://s3-ap-southeast-2.amazonaws.com/my-bucket-name/mypdf.pdf')
    .pipe(res.set('Content-Type', 'application/pdf').set('Content-Disposition', 'inline; filename="mypdf.pdf"'))
})
Sign up to request clarification or add additional context in comments.

8 Comments

yes Arun and thank you for the help. But I have one query, I tried both the approaches and with even with 'Content-Disposition' type inline I am getting an pop up window to download the file. What should be done to show the file in the tab itself.
Also can you try in different browser.
Can you also check the network tab of the browser whether content disposition set to inline. I want to make sure u didn't change after setting
yes, I checked content disposition is set to inline and in mozilla also it is asking to save the file
I think res.attachment(fileInfo[0].fileS3Key) is causing the download
|
0

You can use the AWS SDK for Node.js to generate a signed URL for accessing an S3 object. Here's an example script using Node.js and Express.js:

const AWS = require("aws-sdk");

AWS.config.update({
  accessKeyId: "YOUR_ACCESS_KEY_ID",
  secretAccessKey: "YOUR_SECRET_ACCESS_KEY",
  region: "YOUR_REGION"
});

const s3Client = new AWS.S3();

const params = {
  Bucket: "YOUR_BUCKET_NAME",
  Key: "YOUR_OBJECT_KEY",
  Expires: 60 * 60 * 24 // URL expiration time in seconds (optional)
};

s3Client.getSignedUrl("getObject", params, (err, url) => {
  if (err) {
    console.error("Error generating signed URL:", err);
  } else {
    console.log("Signed URL:", url);
  }
});

The s3Client.getSignedUrl() function generates a signed URL for the specified S3 object using the getObject operation. The params object contains the bucket name, object key, and an optional expiration time for the URL (in seconds).

Remember to ensure that your IAM credentials have the necessary permissions to access the S3 bucket and object. Additionally, you may modify the code to suit your application's needs.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.