关于heroku:使用JqueryFileUpload的Ruby on Rails Direct AWS S3上传

Ruby on Rails Direct AWS S3 Upload with JqueryFileUpload

我想为我的网站构建一个简单的文件上传系统(仅我将要访问和上传)以上传我的投资组合页面。我的网站是在Heroku上托管的Ruby on Rails上。

因此,我遵循Heroku教程将图像上传到S3。它使用aws-sdk gem。在完成本教程的操作后,当我尝试上传简单的.png文件时,收到以下错误。

1
Bad Request 400: Bucket POST must contain a field named 'key'.  If it is specified, please check the order of the fields.

PortfolioController

1
2
3
4
 def new
    @s3_direct_post = S3_BUCKET.presigned_post(key:"${filename}", success_action_status: 201, acl: :public_read)
    @portfolio = Portfolio.new()
  end

在视图中检查javascript formData值:

1
2
3
4
5
6
7
8
9
10
11
12
...
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,

...

给予:

1
2
3
4
5
6
7
8
{
"AWSAccessKeyId"=>"my-access-key",
"key"=>"${filename}",
"policy"=>"long-string",
"signature"=>"randomg-signature-string",
"success_action_status"=>"201",
"acl"=>"public-read"
}

我尝试添加以同步我的时间,如/config/initializers/aws.rb中所示:

1
2
3
4
5
6
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和Java较不熟悉,所以我不确定如何解决此问题。

任何建议,我们将不胜感激。谢谢!


我最近正在处理相同的问题,这是解决方案:

您只需更改此

1
formData:  '<%=@s3_direct_post.fields.to_json.html_safe %>'

对此:

1
formData:  <%=@s3_direct_post.fields.to_json.html_safe %>

因为@s3_direct_post.fields.to_json.html_safe会给你这样的东西:

1
{"key":"value","key":"value","key":"value"}

并通过将其package在' '之间将使其像这样:

1
'{"key":"value","key":"value","key":"value"}'

哪个不是有效的JSON

另一种解决方案(但效率不高,因为我认为第一种更优雅)

通过查看jquery文件上传文档,它说:

By default, the plugin calls jQuery's serializeArray method on the
upload form to gather additional form data for all input fields
(including hidden fields)

因此您可以将这些字段添加到表单中(在文件输入之前),如下所示:

1
2
3
4
5
6
7
<% @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),这会给您带来错误,因为Amazon S3不会接受该错误!

这是我要解决的一个小技巧:

制作与初始表单不同的表单,并为其分配一个ID,在我的情况下,该ID为fields-for-s3

1
2
3
4
5
6
7
8
<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 %>

然后在表单(具有特定ID)上使用jQuery serializeArray()方法手动创建formData对象,如下所示:

1
formData: $('form#fields-for-s3').serializeArray()

我希望有帮助。


我遇到了同样的问题:
你也可以打电话
JSON.parse(formdata);
来自您的javascript。


我决定改用Paperclip Heroku教程,并能够成功上传到S3。

希望这对遇到相同问题的人有所帮助。