如何解决当用户尝试将歌曲上传到我的Rails 6应用时,从AWS S3的PUT请求接收“错误请求400”
我将Rails 5应用程序升级到Rails6。在此更新期间,我将aws-sdk从v1更新到了v3。如文档中所述,我已经在我的gemfile中包含了aws-sdk-s3
gem。
我的应用程序的主要功能之一是允许用户上传歌曲。当我尝试手动测试此功能时,遇到以下错误:
PUT https://bucketname.s3.amazonaws.com/ 400 (Bad Request)
以下是随附的XML:
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>request id code</RequestId>
<HostId>host id code</HostId>
</Error>
在S3 documentation中,我试图检查如何解决该问题,但在那里我发现了另一个令人困惑的细节。当我的控制台返回400状态代码时,“ AccessDenied”实际上在文档中被写为403状态代码。
我要附加上载模型。注释掉的行是我原来的代码行。我根据S3文档中提到的内容进行了更改。
class Upload
attr_reader :filename
# New lines of code: ####################################################
require 'aws-sdk-s3'
Aws.config.update({
region: 'us-east-1',credentials: Aws::Credentials.new(Rails.application.credentials.dig(:aws,:access_key_id),Rails.application.credentials.dig(:aws,:secret_access_key)),})
#########################################################################
def initialize(filename)
@filename = filename
end
def url
#@url ||= bucket_file.url_for(:write,content_type: content_type,acl: :public_read).to_s
@url ||= bucket_file.url().to_s
end
def content_type
@content_type ||= MIME::Types.type_for(filename).first.content_type
end
def to_json(*args)
{ url: url,content_type: content_type }.to_json
end
private
def bucket_file
#@bucket_file ||= bucket.object("uploads/#{SecureRandom.uuid}/#{filename}")
@bucket_file ||= bucket.presigned_post(key: "uploads/#{SecureRandom.uuid}/${filename}",success_action_status: '201',acl: 'public_read',content_type: content_type)
end
def bucket
#@bucket ||= AWS::S3.new.buckets(ENV['S3_BUCKET_NAME'])
@bucket ||= Aws::S3::Resource.new(region: 'us-east-1').bucket(Rails.application.credentials.dig(:aws,:bucket))
end
end
重要的是要提到我确保凭据可访问且有效。
解决方法
不推荐使用url_for
函数,因此必须将其更改为public_url
。
这是我原始代码的有效版本:
class Upload
attr_reader :filename
require 'aws-sdk-s3'
Aws.config.update({
region: 'us-east-1',credentials: Aws::Credentials.new(Rails.application.credentials.dig(:aws,:access_key_id),Rails.application.credentials.dig(:aws,:secret_access_key)),})
def initialize(filename)
@filename = filename
end
def url
@url ||= bucket_file.public_url().to_s
end
def content_type
@content_type ||= MIME::Types.type_for(filename).first.content_type
end
def to_json(*args)
{ url: url,content_type: content_type }.to_json
end
private
def bucket_file
@bucket_file ||= bucket.object("uploads/#{SecureRandom.uuid}/${filename}")
end
def bucket
@bucket ||= Aws::S3::Resource.new(region: 'us-east-1').bucket(Rails.application.credentials.dig(:aws,:bucket))
end
end
,
遇到与您描述的问题类似的问题。
请注意,尽管您已解决了该问题,但由于生产环境强制执行更严格的csrf令牌法规,因此在进入生产环境之前,您需要进行进一步的调整。
这里有进一步的解释:https://docs.aws.amazon.com/AmazonS3/latest/API/archive-RESTObjectPUT.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。