使用 S3 Presigned-URL 上传文件,然后将具有 public-read 访问权限

Using S3 Presigned-URL for upload a file that will then have public-read access

我在 Rails 和 AWS gem 上使用 Ruby。 我可以获得预签名 URL 用于上传和下载。 但是当我得到 URL 时没有文件,所以将 acl 设置为 'public-read' 下载-url 不工作。

用例是这样的:1,服务器为用户提供了一个路径,用于将内容上传到我的存储桶,如果没有凭据则该存储桶不可读。 2,并且该内容需要 public 之后:任何人都可以阅读。

澄清一下: 我没有上传文件,我提供 URL 供我的用户上传。那个时候我也想给用户一个public可读的URL。好像我自己上传文件会容易一些。另外,阅读 URL 需要永不过期。

你有两个选择:

  • 当您 PUT 对象时,将对象的 ACL 设置为 'public-read'。这允许您在没有签名的情况下使用 public url 来获取对象。
  • 让对象上的 ACL 默认为私有,并为用户提供预签名的 GET url。这些会过期,因此您必须根据需要生成新的 URL。预签名 URL 允许某人在没有凭据的情况下向对象发送 GET 请求。

上传一个public对象并生成一个public url:

require 'aws-sdk'

s3 = Aws::S3::Resource.new
s3.bucket('bucket-name').object('key').upload_file('/path/to/file', acl:'public-read')
s3.public_url
#=> "https://bucket-name.s3.amazonaws.com/key"

上传私有对象并生成 GET url 1 小时有效:

s3 = Aws::S3::Resource.new
s3.bucket('bucket-name').object('key').upload_file('/path/to/file')
s3.presigned_url(:get, expires_in: 3600)
#=> "https://bucket-name.s3.amazonaws.com/key?X-Amz-Algorithm=AWS4-HMAC-SHA256&..."

当您为 PUT object 请求生成 pre-signed URL 时,您可以指定上传者必须使用的密钥和 ACL。如果我希望用户使用密钥 "files/hello.txt" 将对象上传到我的存储桶并且该文件应该是公开可读的,我可以执行以下操作:

s3 = Aws::S3::Resource.new
obj = s3.bucket('bucket-name').object('files/hello.text')

put_url = obj.presigned_url(:put, acl: 'public-read', expires_in: 3600 * 24)
#=> "https://bucket-name.s3.amazonaws.com/files/hello.text?X-Amz-..."

obj.public_url
#=> "https://bucket-name.s3.amazonaws.com/files/hello.text"

我可以把 put_url 给别人。 URL 将允许他们将 object 放入 URL。它具有以下条件:

  • PUT 请求必须在给定的有效期内发出。在上面的示例中,我指定了 24 小时。 :expires_in 选项不得超过 1 周。
  • PUT 请求必须指定 'x-amz-acl' 的 HTTP header,值为 'public-read'。

使用 put_url,我可以使用 Ruby 的 Net::HTTP:

上传任何 object
require 'net/http'

uri = URI.parse(put_url)

request = Net::HTTP::Put.new(uri.request_uri, 'x-amz-acl' => 'public-read')
request.body = 'Hello World!'

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true   
resp = http.request(request)

现在 object 已由其他人上传,我可以向 #public_url 发出普通 GET 请求。这可以通过浏览器、curl、wget 等来完成。