Rails:上传 dropzone、S3、carrierwave,不能在 Safari 中工作,但在 Google Chrome 中工作
Posted
技术标签:
【中文标题】Rails:上传 dropzone、S3、carrierwave,不能在 Safari 中工作,但在 Google Chrome 中工作【英文标题】:Rails: Uploading dropzone, S3, carrierwave, not working in Safari, but works in Google Chrome 【发布时间】:2016-03-16 22:17:25 【问题描述】:我正在使用带有 S3 和载波的 dropzone。我可以通过谷歌浏览器上传图片,但我无法让它与 Safari 一起使用,这很奇怪。
这是我的表格
= nested_form_for @trip, html: multipart: true, id: 'fileupload', class: 'directUpload', data: 'form-data' => (@s3_direct_post.fields), 'url' => @s3_direct_post.url, 'host' => URI.parse(@s3_direct_post.url).host do |f|
.dropzone#imageUpload
= f.simple_fields_for :trip_images, TripImage.new, child_index: TripImage.new.object_id do |ff|
= ff.file_field :photo, class: 'hide form-fields'
= f.button :submit, id: "submit-data"
这是在 Trip 控制器中
def set_s3_direct_post
@s3_direct_post = S3_BUCKET.presigned_post(key: "/uploads/temporary/#SecureRandom.uuid/$filename", success_action_status: '201', acl: 'public-read', content_type: 'image/jpeg')
end
这是 TripImage 模型
class TripImage < ActiveRecord::Base
belongs_to :resource, :polymorphic => true
mount_uploader :photo, PhotoUploader
after_create :process_async
def to_jq_upload
'name' => read_attribute(:attachment_file_name),
'size' => read_attribute(:attachment_file_size),
'url' => attachment.url(:original),
'thumbnail_url' => attachment.url(:thumb),
'delete_url' => "/photos/#id",
'delete_type' => 'DELETE'
end
private
def process_async
PhotoVersioningJob.set( wait: 5.seconds ).perform_later(self.id)
end
end
这是js
$(function()
$('.directUpload').find(".dropzone").each(function(i, elem)
s3ImageUpload(elem);
);
)
function s3ImageUpload(elem)
var fileInput = $(elem);
var form = $(fileInput.parents('form:first'));
var form_url = form.data('url');
var form_data = form.data('form-data');
Dropzone.options.imageUpload =
url: form_url,
params: form_data,
uploadMultiple: false,
addRemoveLinks: true,
removedfile: function(file)
//some codes
,
success: function(file, serverResponse, event)
//some codes
,
error: function(data)
//some codes
;
编辑:当前 CORS 配置
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*.example.com</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
<AllowedHeader>origin</AllowedHeader>
</CORSRule>
</CORSConfiguration>
经过测试,无法正常工作
编辑:我也有 S3 直接上传,不确定这是否也会影响它?
S3DirectUpload.config do |c|
c.access_key_id = Rails::AWS.config['access_key_id'] # your access key id
c.secret_access_key = Rails::AWS.config['secret_access_key'] # your secret access key
c.bucket = Rails::AWS.config['bucket_name'] # your bucket name
c.region = 's3' # region prefix of your bucket url. This is _required_ for the non-default AWS region, eg. "s3-eu-west-1"
end
【问题讨论】:
我无权访问 safari,但我想请求上方的行可能包含 safari 不支持的调用。变量fileInput、form、form_url和form_data分别包含哪些数据? 在使用 chrome 时这些变量包含哪些数据? 如何在 Safari 中失败?在控制台中看到任何错误? @PabloKarlsson 所以我可以在控制台中查看,它确实在trip_images_attributes
中传递了临时 amazon aws url 参数,但我只是想知道为什么它不保存 chrome 保存的方式?
INSERT INTO
是最后一步,尝试调试前面的步骤。是从 Safari 发出正确的请求,还是根本没有请求?如果是,从 Chrome 和 Safari 发送的参数有何不同?
【参考方案1】:
我最近在 Safari 上遇到了类似的问题,并发现它正在发送一个额外的 Access-Control-Request-Header,而 Chrome 没有——特别是“来源”。为了解决这个差异,我需要更新目标存储桶上的 AWS CORS 配置。
AWS Documentation on the necessity of request headers matching an allowed header config。第三个要点明确了这一要求:
预检请求的 Access-Control-Request-Headers 标头中列出的每个标头都必须与 AllowedHeader 元素匹配。
This helpful *** answer 给出了一个示例配置:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Authorization</AllowedHeader>
<AllowedHeader>x-requested-with</AllowedHeader>
</CORSRule>
</CORSConfiguration>
以及需要添加什么才能使其在 Safari 中运行:
<AllowedHeader>origin</AllowedHeader>
【讨论】:
我希望这能解决问题。我更新了我的问题以显示我的 CORS 配置是什么。这是它应该看起来的样子吗? 另外,我不确定它是否存在 CORS 问题?我正在查看 heroku 日志,但它没有插入数据库。这发生在 Chrome 中。 @hellomello 是的,假设 *.example.com 实际上是您的网站主机名。此外,您需要确保您没有获得飞行前响应的缓存版本,在您的情况下,该响应最多会停留 3000 秒。如果它仍然不适合您,我只能想到我们遇到的另一个问题,即尝试从 http 页面调用 https url 或相反。我不是您使用的堆栈方面的专家,但我在直接 s3 上传方面有相当多的经验。我做出这个答案的唯一原因是它的呈现方式完全相同(仅在 safari 中不工作) @hellomello 是进入 s3 存储桶的文件吗? 不,它没有被保存到存储桶中。我可以在 heroku 日志中看到表单正在生成表单参数中的亚马逊 URL,即:https://<bucket-name>.s3.amazon.aws.com/%2Fuploads%2Ftemporary%2Frandomnumbers.jpg
,但是当我在存储桶中时,它不存在。我想它也不会保存到数据库记录中。网址是 https,我的网站是 http。以上是关于Rails:上传 dropzone、S3、carrierwave,不能在 Safari 中工作,但在 Google Chrome 中工作的主要内容,如果未能解决你的问题,请参考以下文章
Rails 6主动存储sidekiq文件在S3上上传背景图片
使用 plupload 和 Rails 3 的 Amazon S3 分段上传