如何使用Javascript从Amazon S3存储桶下载文件?

64

我正在尝试从Amazon S3存储桶下载文件。 我想知道是否可以编写JavaScript来从存储桶下载此类文件。 我搜索了一下,但找不到任何可以帮助我完成此操作的资源。

我的思路是:首先验证Amazon S3,然后提供存储桶名称和文件(key),下载或读取文件以便能够显示文件中的数据。

谢谢。


你可以在<a>标签上使用download属性来触发下载而不是导航。 - dandavis
但这并不简单,因为我们需要处理Amazon S3凭据。 - c0mrade
1
只要用户处于“登录”状态,它就可以正常工作。Cookie 可以让用户保持一段时间的登录状态,这样您就不必在 S3 HTML 页面上才能使用链接... 如果您需要身份验证帮助,那么这实际上是另一个问题,但在您使用 JavaScript 自动下载之前,您需要先回答这个问题。 - dandavis
3个回答

62

也许您可以使用 AWS Node.js API:

var AWS = require('aws-sdk');
AWS.config.update(
  {
    accessKeyId: ".. your key ..",
    secretAccessKey: ".. your secret key ..",
  }
);
var s3 = new AWS.S3();
s3.getObject(
  { Bucket: "my-bucket", Key: "my-picture.jpg" },
  function (error, data) {
    if (error != null) {
      alert("Failed to retrieve an object: " + error);
    } else {
      alert("Loaded " + data.ContentLength + " bytes");
      // do something with data.Body
    }
  }
);

4
这里是 AWS Node.js API 中 s3.getObject 的直接链接,供有兴趣的人参考。 - Naruto Sempai
2
对于任何想知道的人,data.Body是原始文件,可以在其他模块中使用,比如graphicsmagick:gm(data.Body).identify(function (err, value) {});非常酷! - The Unknown Dev
6
您可以在Node中像这样保存(下载)文件:fs.writeFile(“mydata.tsv.gz”,data.Body); - cemsazara
2
第一眼看到服务器端代码中的 alert,我感到非常惊讶 :) - Abdul Hameed
1
我可能漏掉了什么,但是这个脚本似乎不安全,不能在浏览器中包含。具体来说,明文列出 secretAccessKey - undeniablyrob
显示剩余3条评论

51

我来这里是为了寻找一种在客户端下载S3文件的方法。以下是我的解决方案:

由于我不能将我的S3认证密钥存储在客户端上,因此我使用我的服务器端脚本生成预签名URL,并像这样将其发送回客户端:

const AWS = require('aws-sdk')

const s3 = new AWS.S3()
AWS.config.update({accessKeyId: 'your access key', secretAccessKey: 'you secret key'})

const myBucket = 'bucket-name'
const myKey = 'path/to/your/key/file.extension'
const signedUrlExpireSeconds = 60 * 5 // your expiry time in seconds.

const url = s3.getSignedUrl('getObject', {
 Bucket: myBucket,
 Key: myKey,
 Expires: signedUrlExpireSeconds
})

// return the url to client

使用此URL在前端触发下载:

function download(url){
    $('<iframe>', { id:'idown', src:url }).hide().appendTo('body').click();
}
$("#downloadButton").click(function(){
    $.ajax({
        url: 'example.com/your_end_point',
        success: function(url){
            download(url);
        }
    })
});

2
什么是签名URL?编辑:今天我了解到,https://advancedweb.hu/2018/10/30/s3_signed_urls/。 - undeniablyrob
3
我发现如果我在新标签页中使用签名 URL:window.open(signedUrl, '_blank'); 而不是 iframe,浏览器可以更好地处理下载文件中的混合 MIME 类型(二进制、图像等),否则这是一个非常有帮助的答案。 - slh777
您可以在此处阅读有关 AWS 的 Python 示例的更多信息:https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-presigned-urls.html - Yohan Obadia
@slh777,我该如何使用axios来下载那个signedUrl的文件呢?有什么想法吗? - Blaze

3

这里的其他答案都是可行的,但我想进一步解释一下对我有用的方法。

在我的情况下,我处理的文件太大了,无法使用

function download(url){
    $('<iframe>', { id:'idown', src:url }).hide().appendTo('body').click();
}

工作时遇到了 url 过长 的问题。

我的解决方案是包含一个隐藏的锚点标签,然后在 ajax 成功时触发该标签的点击事件。如果你不在意处理错误,就不能直接使用锚点标签。

如果出现问题,S3 将会响应一个 XML 错误文件,因此浏览器将自动显示该 XML 响应。通过先尝试使用 ajax 命中 URL,你可以在不显示丑陋的 XML 的情况下捕获该错误。当 ajax 调用成功时,你就知道可以尝试下载文件了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接