Ruby on Rails直接使用JqueryFileUpload上传AWS S3

时间:2015-01-29 11:26:14

标签: ruby-on-rails heroku amazon-web-services amazon-s3 jquery-file-upload

我想为我的网站构建一个简单的文件上传系统(只有我将访问和上传)才能上传我的投资组合页面。我的网站是在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相对较新,所以我不确定如何解决这个问题。

任何建议表示赞赏。谢谢!

3 个答案:

答案 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。