如何在 Ruby 中将预签名的 POST 文件上传到 AWS S3?
How to do a Pre-signed POST file upload to AWS S3 in Ruby?
与有关。
我想将预签名的 POST 文件上传到 AWS S3 上的存储桶,该存储桶只有 public-read 使用以下存储桶策略:
{
"Version": "2012-10-17",
"Id": "Policy1441191234567",
"Statement": [
{
"Sid": "Stmt1441195123456",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::mytestbucket/*"
}
]
}
已创建预签名 URL,任何拥有它的人都可以使用 HTTP POST 进行上传,如所述 here。
我已成功使预签名 PUT 正常工作,如 here 所述。 IE。我在 ~/aws/credentials
中有适当的凭据,可以完全访问存储桶。
在存储桶的 AWS Ruby SDK, I have found that there’s a PresignedPost 中,所以我尝试了以下操作:
require 'aws-sdk-resources'
require 'net/http'
require 'time'
require 'uri'
s3 = Aws::S3::Resource.new(region:'eu-central-1')
bucket = s3.bucket('mytestbucket')
post = bucket.presigned_post({
key: 'larry',
acl: "public-read",
expires: Time.now() + 30,
content_length_range: 1...1024,
success_action_redirect: "https://example.com/callback",
})
puts post.url
puts post.fields
uri = URI(post.url)
fields = post.fields.merge(file: "ken sent me")
res = Net::HTTP.post_form(uri, fields)
puts res.body
不幸的是,运行 这会导致错误:
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>InvalidArgument</Code><Message>Conflicting query string parameters: acl, policy</Message><ArgumentName>ResourceType</ArgumentName><ArgumentValue>acl</ArgumentValue><RequestId>6132C47A14212345</RequestId><HostId>abcdKciFUKxvC4717Zm9w2ZB5lXJna+NSkxXzkb9123tjHZHb60JJa123KctSu862gY/j+a5+3w=</HostId></Error>
我曾尝试删除 acl
字段,但这会导致另一个错误:
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>MethodNotAllowed</Code><Message>The specified method is not allowed against this resource.</Message><Method>POST</Method><ResourceType>BUCKETPOLICY</ResourceType><RequestId>9B3D7AAAE45BB47F</RequestId><HostId>yk823Z12345uucETlpQaG1234T0lxqjGAX4Uka123LQ6Pf22NVf45xxMmZAlFoQHaP+C4N60oLI=</HostId></Error>
URI 是:https://mytestbucket.s3.eu-central-1.amazonaws.com
有什么问题,我该如何解决?
感谢您的帮助!
更新
如错误之一所述,问题可能是 acl 和存储桶策略冲突。我希望所有人都能阅读它,并且只有使用预签名 URL 才能上传(我假设所有者成为创建 URL 的人)。我以为我是这样设置的。
我认为这里有多种策略在起作用。 bucket policy and the post policy. See also the Ruby docs on PresignedPost -- 您必须搜索 "Post Policy",因为我看不到标题的锚点。看起来 Ruby 为您创建了一个 post 政策,但是:
you must specify every form field name that will be posted by the browser. If you omit a form field sent by the browser, Amazon S3 will reject the request.
另外,这个 PresignedPost which is provided is meant to generate an HTML form which in turn generates the POST request and URL. You could generate that instead of letting the form do it. However if you already know all the details of the URL and request -- as asked in your Go question about the same thing -- why not Upload an Object Using a Pre-Signed URL.
所以我有 ,同样适用于 Ruby。我遇到的问题是正确生成多部分表单数据。
与
我想将预签名的 POST 文件上传到 AWS S3 上的存储桶,该存储桶只有 public-read 使用以下存储桶策略:
{
"Version": "2012-10-17",
"Id": "Policy1441191234567",
"Statement": [
{
"Sid": "Stmt1441195123456",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::mytestbucket/*"
}
]
}
已创建预签名 URL,任何拥有它的人都可以使用 HTTP POST 进行上传,如所述 here。
我已成功使预签名 PUT 正常工作,如 here 所述。 IE。我在 ~/aws/credentials
中有适当的凭据,可以完全访问存储桶。
在存储桶的 AWS Ruby SDK, I have found that there’s a PresignedPost 中,所以我尝试了以下操作:
require 'aws-sdk-resources'
require 'net/http'
require 'time'
require 'uri'
s3 = Aws::S3::Resource.new(region:'eu-central-1')
bucket = s3.bucket('mytestbucket')
post = bucket.presigned_post({
key: 'larry',
acl: "public-read",
expires: Time.now() + 30,
content_length_range: 1...1024,
success_action_redirect: "https://example.com/callback",
})
puts post.url
puts post.fields
uri = URI(post.url)
fields = post.fields.merge(file: "ken sent me")
res = Net::HTTP.post_form(uri, fields)
puts res.body
不幸的是,运行 这会导致错误:
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>InvalidArgument</Code><Message>Conflicting query string parameters: acl, policy</Message><ArgumentName>ResourceType</ArgumentName><ArgumentValue>acl</ArgumentValue><RequestId>6132C47A14212345</RequestId><HostId>abcdKciFUKxvC4717Zm9w2ZB5lXJna+NSkxXzkb9123tjHZHb60JJa123KctSu862gY/j+a5+3w=</HostId></Error>
我曾尝试删除 acl
字段,但这会导致另一个错误:
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>MethodNotAllowed</Code><Message>The specified method is not allowed against this resource.</Message><Method>POST</Method><ResourceType>BUCKETPOLICY</ResourceType><RequestId>9B3D7AAAE45BB47F</RequestId><HostId>yk823Z12345uucETlpQaG1234T0lxqjGAX4Uka123LQ6Pf22NVf45xxMmZAlFoQHaP+C4N60oLI=</HostId></Error>
URI 是:https://mytestbucket.s3.eu-central-1.amazonaws.com
有什么问题,我该如何解决?
感谢您的帮助!
更新
如错误之一所述,问题可能是 acl 和存储桶策略冲突。我希望所有人都能阅读它,并且只有使用预签名 URL 才能上传(我假设所有者成为创建 URL 的人)。我以为我是这样设置的。
我认为这里有多种策略在起作用。 bucket policy and the post policy. See also the Ruby docs on PresignedPost -- 您必须搜索 "Post Policy",因为我看不到标题的锚点。看起来 Ruby 为您创建了一个 post 政策,但是:
you must specify every form field name that will be posted by the browser. If you omit a form field sent by the browser, Amazon S3 will reject the request.
另外,这个 PresignedPost which is provided is meant to generate an HTML form which in turn generates the POST request and URL. You could generate that instead of letting the form do it. However if you already know all the details of the URL and request -- as asked in your Go question about the same thing -- why not Upload an Object Using a Pre-Signed URL.
所以我有