如何使用 aws-sdk 获取 AWS S3 上文件的 URL?

Posted

技术标签:

【中文标题】如何使用 aws-sdk 获取 AWS S3 上文件的 URL?【英文标题】:How to get the URL of a file on AWS S3 using aws-sdk? 【发布时间】:2017-11-08 01:46:06 【问题描述】:

我正在使用 AWS Lambda 函数创建一个文件并将其保存到我在 S3 上的存储桶中,它工作正常。执行putObject 方法后,我得到一个data 对象,但它只包含最近添加的对象的Etag

s3.putObject(params, function(err, data) 
    // data only contains Etag
);

我需要知道可以在浏览器中使用的确切 URL,以便客户端可以看到该文件。该文件夹已公开,如果我从 S3 控制台复制链接,我可以看到该文件。

我尝试使用getSignedUrl,但我相信它返回的 URL 用于其他目的。

谢谢!

【问题讨论】:

预签名的 url 可以用作下载链接,但是,它会在 x 分钟后过期,用于非公共项目。如果您的项目是公开的,最简单的做法就是使用可预测的模式连接 URL。 如果我从 S3 控制台复制链接你看到那里的模式了吗?存储桶中每个对象的 URL 都遵循完全相同的模式。 【参考方案1】:

SDK 通常不包含为公共可读对象创建 URL 的便捷方法。但是,当您调用 PutObject 时, 提供了存储桶和对象的密钥,这就是您所需要的。您可以简单地将它们组合成对象的 URL,例如:

https://bucket.s3.amazonaws.com/key

因此,例如,如果您的存储桶是 pablo 并且对象键是 dogs/toto.png,请使用:

https://pablo.s3.amazonaws.com/dogs/toto.png

请注意,S3 密钥不以 / 前缀开头。密钥的形式为dogs/toto.png,而不是/dogs/toto.png

对于特定于区域的存储桶,请参阅 Working with Amazon S3 Buckets 和 AWS S3 URL Styles。将上述网址中的s3替换为s3.<region>.amazonaws.coms3-<region>.amazonaws.com,例如:

https://seamus.s3.eu-west-1.amazonaws.com/dogs/setter.png(带点) https://seamus.s3-eu-west-1.amazonaws.com/dogs/setter.png(带破折号)

如果您使用的是 IPv6,则一般 URL 格式为:

https://BUCKET.s3.dualstack.REGION.amazonaws.com

对于某些存储桶,您可以使用较旧的路径样式 URL。路径样式的 URL 已被弃用,only work with buckets created on or before September 30, 2020。它们是这样使用的:

https://s3.amazonaws.com/bucket/key https://s3.amazonaws.com/pablo/dogs/toto.png https://s3.eu-west-1.amazonaws.com/seamus/dogs/setter.png https://s3.dualstack.REGION.amazonaws.com/BUCKET

目前存在 TLS 和 SSL 证书问题,可能需要通过路径样式的 URL 访问某些名称中带有点 (.) 的存储桶。 AWS 计划解决这个问题。请参阅AWS announcement。

注意:关于 object keys 某些字符需要特殊处理的一般指导。例如,空格编码为 +(加号),加号编码为 %2B。还有here。

【讨论】:

谢谢!我认为链接在某些命名场景中很容易发生意外更改。 关于命名注意事项的附加帖子:***.com/questions/7116450/… 这并不能解释如果您在上传的文件名中使用空格会发生什么。显然它们被替换为“+”,但也许还有更多这样的规则? @JorisMans 谢谢,添加了额外的参考资料。 就我而言,我也需要存储桶区域:http://s3.region.amazonaws.com/bucket/key。对我来说,地区是eu-west-3【参考方案2】:

如果您有 s3bucket 和文件名对象并想要提取 url,这里有一个选项:

function getUrlFromBucket(s3Bucket,fileName)
    const config :params,region = s3Bucket;
    const regionString = region.includes('us-east-1') ?'':('-' + region)
    return `https://$params.Bucket.s3$regionString.amazonaws.com/$fileName`
;

【讨论】:

这不适用于非区域特定的存储桶。例如,us-east-1 中的存储桶没有该区域作为 url 的一部分。 @bPratik ,感谢您的评论,我编辑了代码以支持它... 也没有正确转义键 @jrochkind 是什么意思?【参考方案3】:

你可以用这个打另一个电话:

var params = Bucket: 'bucket', Key: 'key';
s3.getSignedUrl('putObject', params, function (err, url) 
  console.log('The URL is', url);
);

【讨论】:

仅在一定时间内有效 只有在 s3 文件不公开的情况下,获取签名的 url 才有意义

以上是关于如何使用 aws-sdk 获取 AWS S3 上文件的 URL?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 aws-sdk 中的 s3 存储桶创建 Elastic Beanstalk 实例?

@aws-sdk/lib-storage 使用 JSONStream.stringify() 将 JSON 从 MongoDB 流式传输到 S3

使用 aws-sdk 将 gm 调整大小的图像流上传到 s3

为啥我在 s3 上的访问被拒绝(使用适用于 Node.js 的 aws-sdk)?

Ruby v2 的 aws-sdk:在我将对象放入 S3 存储桶后检查成功状态

通过使用 AWS-SDK PHP 生成的预签名帖子拒绝 AWS S3 上传访问