Ruby Rails 使用 Jquery FileUpload 直接上传 AWS S3
Ruby on Rails Direct AWS S3 Upload with JqueryFileUpload
我想为我的网站构建一个简单的文件上传系统(只有我会访问和上传)来上传我的投资组合页面。我的网站在 Rails 上 Ruby,托管在 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.
投资组合控制器
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 和 Whosebug 后,似乎 Jquery 可能正在重建表单数据,因此弄乱了 POST 值的顺序。
问题是,我对 Rails 和 Javascript 上的 Ruby 比较陌生,所以我不确定如何解决这个问题。
如有任何建议,我们将不胜感激。谢谢!
我决定改用 Paperclip Heroku Tutorial,并成功上传到 S3。
希望这对遇到同样问题的人有所帮助。
我最近遇到了同样的问题,这就是解决方案:
你只需要改变这个
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 它说:
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)
因此您可以像这样将这些字段添加到表单中(在文件输入之前):
<% @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
<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()
希望对您有所帮助。
我运行遇到同样的问题:
你也可以打电话
JSON.parse(表单数据);
来自你的 javascript.
我想为我的网站构建一个简单的文件上传系统(只有我会访问和上传)来上传我的投资组合页面。我的网站在 Rails 上 Ruby,托管在 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.
投资组合控制器
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 和 Whosebug 后,似乎 Jquery 可能正在重建表单数据,因此弄乱了 POST 值的顺序。
问题是,我对 Rails 和 Javascript 上的 Ruby 比较陌生,所以我不确定如何解决这个问题。
如有任何建议,我们将不胜感激。谢谢!
我决定改用 Paperclip Heroku Tutorial,并成功上传到 S3。
希望这对遇到同样问题的人有所帮助。
我最近遇到了同样的问题,这就是解决方案:
你只需要改变这个
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 它说:
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)
因此您可以像这样将这些字段添加到表单中(在文件输入之前):
<% @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
<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()
希望对您有所帮助。
我运行遇到同样的问题: 你也可以打电话 JSON.parse(表单数据); 来自你的 javascript.