Unable to download a file from S3 by the URL in a browser
Asked Answered
C

3

6

I have such code snippet that used to be work with the previous versions of Google Chrome, but now it does not work. When I run this script I redirected to the page with the content of the file(it's a text) and with AWS URL(the same as in setAttribute).

var element = document.createElement('a');
element.setAttribute('href', 'https://s3-us-east-1.amazonaws.com/XXX/XXX/XXX?Signature=XXX&Expires=XXX&AWSAccessKeyId=XXX');
element.setAttribute('download', 'filename.txt');
document.body.appendChild(element);
element.click();

How to download this file?

Conditional answered 3/5, 2018 at 9:6 Comment(8)
Maybe it's to do with settings on the browser how to behave when a download link it clicked? Chrome "opens" a lot of file extensions by default in a previewer rather than downloading the files.Crumley
@Crumley I'm not able to change settings on the user's browsers.Conditional
check if HTTP header Content-Disposition is present in the response headers and if it's set to "filename.txt".Excruciate
@Excruciate Yes, it's present: Content-Disposition: inline;filename=filename.txt;filename*=UTF-8''filename.txtConditional
Here your problem lies: Content-Disposition: inline, it should be Content-Disposition: attachment. Browsers ( and latest verstions of Chrome) favour Content-Disposition header over download attributeExcruciate
@Excruciate Can I add Content-Disposition: attachment parameter to the URL?Conditional
No, you can't. I assume you have an access to S3 management console ? It's is possible to edit file's metadata. check this tutorial: iwantmyreal.name/s3-download-only-presigned-uploadExcruciate
Block cross-origin <a download>Zaibatsu
E
2

I made an error in the comments. Chrome still favours download attribute, but it completely ignores it if the anchor element has cross origin attributes ( meaning, if the file is hosted on a different domain).

To be able to download it, file needs to be served with header: Content-Disposition: attachment;

Check this tutorial to see how to set Content-Disposition in s3 management console: http://iwantmyreal.name/s3-download-only-presigned-upload

Excruciate answered 3/5, 2018 at 10:6 Comment(0)
W
2

Here is my solution:

    let downloadImage = url => {
      let urlArray = url.split("/")
      let bucket = urlArray[3]
      let key = `${urlArray[4]}/${urlArray[5]}`
      let s3 = new AWS.S3({ params: { Bucket: bucket }})
      let params = {Bucket: bucket, Key: key}
      s3.getObject(params, (err, data) => {
        let blob=new Blob([data.Body], {type: data.ContentType});
        let link=document.createElement('a');
        link.href=window.URL.createObjectURL(blob);
        link.download=url;
        link.click();
      })
    }

The url parameter refers to the full url of the image.

Worriment answered 12/11, 2018 at 20:53 Comment(1)
I had to use new Blob([new Uint8Array(data.Body.data)], {type: data.ContentType}) for this to workTainataint
P
0

I ran into a scenario in which I was setting the href property of the link dynamically, and my string transformation was encoding the character & into &amp;.

As so:

https://some-bucket.amazonaws.com/filename.txt?X-Amz-Algorithm=XXX-XXX-XXX&amp;[...]

The URL broke after the first &amp; string.

Pumping answered 9/9 at 16:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.