我想为我的网站构建一个简单的文件上传系统(只有我将访问和上传)才能上传我的投资组合页面。我的网站是在Ruby on Rails上,托管在Heroku上。
所以我跟着Heroku Tutorial将图片上传到S3。它使用aws-sdk
gem在完成教程之后,当我尝试上传一个简单的.png文件时,我收到了以下错误。
Bad Request 400: Bucket POST must contain a field named 'key'. If it is specified, please check the order of the fields.
PortfolioController
def new
@s3_direct_post = S3_BUCKET.presigned_post(key: "${filename}", success_action_status: 201, acl: :public_read)
@portfolio = Portfolio.new()
end
检查视图中的javascript formData
值:
...
fileInput.fileupload({
formData: '<%=@s3_direct_post.fields.to_json.html_safe %>',
fileInput: fileInput,
url: '<%=@s3_direct_post.url%>',
type: 'POST',
autoUpload: true,
paramName: 'file',
dataType: 'XML',
replaceFileInput: false,
...
给出:
{
"AWSAccessKeyId"=>"my-access-key",
"key"=>"${filename}",
"policy"=> "long-string",
"signature"=>"randomg-signature-string",
"success_action_status"=>"201",
"acl"=>"public-read"
}
我已尝试添加以同步我的时间,如/config/initializers/aws.rb
:
AWS.config(access_key_id: ENV['AWS_ACCESS_KEY_ID'],
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'])
AWS::S3.const_set('DEFAULT_HOST', "s3-ap-southeast-1.amazonaws.com")
S3_BUCKET = AWS::S3.new.buckets[ENV['S3_BUCKET']]
在查看Google和Stackoverflow之后,似乎Jquery可能正在重建表单数据,因此搞乱了POST值的顺序。
问题是,我对Ruby on Rails和Javascript相对较新,所以我不确定如何解决这个问题。
任何建议表示赞赏。谢谢!
答案 0 :(得分:1)
我最近处理同样的问题,这就是解决方案:
你只需要改变这个
formData: '<%=@s3_direct_post.fields.to_json.html_safe %>'
对此:
formData: <%=@s3_direct_post.fields.to_json.html_safe %>
因为@s3_direct_post.fields.to_json.html_safe
会给你这样的东西:
{"key":"value", "key":"value", "key":"value"}
并将其包裹在' '
之间,它会像这样:
'{"key":"value", "key":"value", "key":"value"}'
哪个不是有效的JSON
另一个解决方案(但效率不高,因为我认为第一个更优雅)
通过查看jquery文件上传documentation,它说:
默认情况下,插件调用jQuery的serializeArray方法 上传表单以收集所有输入字段的其他表单数据 (包括隐藏字段)
所以你可以将这些字段添加到表单(文件输入之前的 ),如下所示:
<% @s3_direct_post.fields.map do |name, value| %>
<input type="hidden" name="<%= name %>" value="<%= value %>" />
<% end %>
<%= f.file_field :avatar_url%>
...
...
但要注意因为文档会告诉你它将收集所有字段,包括隐藏字段(在你的Rails应用程序中有一些额外的隐藏字段,如utf8和authenticity_token),这会给你一个错误,因为亚马逊S3不接受这一点!
这是我为解决这个问题所做的一点点工作:
制作一个与初始表单不同的表单,并为其指定一个ID ,在我的情况下,ID为 fields-for-s3
<form id="fields-for-s3">
<% @s3_direct_post.fields.map do |name, value| %>
<input type="hidden" name="<%= name %>" value="<%= value %>" />
<% end %>
</form>
<%= form_for @user, ..... %>
....
<% end %>
然后在表单上使用jQuery serializeArray()方法(使用特定ID)手动创建一个formData对象:
formData: $('form#fields-for-s3').serializeArray()
我希望这有帮助。
答案 1 :(得分:0)
我决定关注Paperclip Heroku Tutorial,并成功上传到S3。
希望这可以帮助任何有同样问题的人。
答案 2 :(得分:0)
我遇到了同样的问题: 你也可以打电话 JSON.parse(FORMDATA); 来自您的JavaScript。