2

I am trying to create a signed URL to allow for downloading a file from an AWS S3 bucket. To my Node.JS lambda function, I pass it a file name and it will create a signed url that I then trigger on the client side to download the file. This works well for .docx files, but does not work for .txt. Instead, the signedurl provided when clicked opens the file in the browser/console. Does something need to be done differently when generating the signed url to work with .txt files?

I have tried troubleshooting the issue and believe it is the difference in file types. I originally thought it may have to do with file names and escape characters affecting it, but I renamed the .txt file and stripped it of any special characters and it still fails. The issue is also not caused by differing file sizes as I created two identical files (one .docx and the other .txt) and the .docx file downloaded as expected. The .txt file would not.

Here is the code I am using to download files from an S3 bucket

//creates signed url that is returned to client side
const url = s3.getSignedUrl('getObject', {
        Bucket: myBucket,
        Key: myPassedInKey,
        Expires: signedUrlExpireSeconds
        });

        responseBody = {
            success: true,
            url: url
        };
//give the signed url and it will download it
function download(url) {
    $('<iframe>', { id: 'idown', src: url }).hide().appendTo('body').click();
}

I expect the file to download the file into the download folder, but instead it does not. When debugging if you enter the signed url into the browser it just opens the file on the browser page instead of downloading like it does with .docx files

EDIT

I believe my question differs from the suggestion below. I am looking to find out why the signed url generation works as expected for a .docx file and not a .txt.

shiley
  • 41
  • 7
  • Possible duplicate of [How to add Content-Disposition to a pre-authenticated Amazon S3 link](https://stackoverflow.com/questions/8062684/how-to-add-content-disposition-to-a-pre-authenticated-amazon-s3-link) – stdunbar Jun 03 '19 at 20:01
  • 1
    Ultimately, without a `Content-Disposition` HTTP header, it's up to the browser. Your browser decided that it didn't know how to deal with `.docx` files and asked to save it. It knew how to handle `.txt` files and displayed it. – stdunbar Jun 03 '19 at 20:25

2 Answers2

2

Thank you to @DevenA and @stdunbar for their help with solving the problem I was having. They were both correct in needing to add a 'Content Disposition' header in order to force a download instead of it opening it in the browser. Below is the change I made to the code generating a signed url.

var contentDisposition = 'attachment; filename=\"' + myPassedInKey + '\"';
const url = s3.getSignedUrl('getObject', {
Bucket: myBucket,
Key: myPassedInKey,
ResponseContentDisposition: contentDisposition,
Expires: signedUrlExpireSeconds
});

The code above now downloads the .txt as desired

shiley
  • 41
  • 7
0

I'm guessing that the problem is that most browsers will try to render txt in the browser itself, whereas they tend to have no handler for docx, so they'll automatically default to prompt the user to download the file.

You may have to add "content disposition" header and/or add

style: "visibility:hidden;display:none"

in the iframe construct.

DevenA
  • 1
  • 1
  • Thank you for your response. What would I have to add with the content disposition header in order to make file download of a .txt file possible? – shiley Jun 03 '19 at 20:54