【发布时间】:2017-06-14 07:31:21
【问题描述】:
我在 Ember 中使用 dropzone 插件 (ember-cli-dropzonejs) 实现了图像上传。 Rails 5 在服务器(Ubuntu 14.x)上运行,imagemagick 安装在 Rails Docker 容器中,所有文件都应该放在“uploads”文件夹中。 一切都作为 docker 容器运行,因此 rails、前端、数据库和 nginx (1.11.4) 是独立的容器。 现在,如果我尝试上传图片,服务器响应是 405,并且 rails 没有得到任何东西(日志中什么都没有)。
ember hbs 文件
{{drop-zone url=uploadURL
method='PATCH'
headers=authentication acceptedFiles='.jpg, .jpeg, .gif, .png'
resize=''
maxFilesize='10'
dictDefaultMessage='Upload file'
success=(action 'succesfulFileUpload')
complete=resetUploader
previewTemplate='<div></div>'
uploadprogress=progressManipulation
sending=sending
}}
rails uploader.rb
class AvatarUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
# Choose what kind of storage to use for this uploader:
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
version :thumb do
process resize_to_fill: [200, 200]
end
# Add a white list of extensions which are allowed to be uploaded.
# For images you might use something like this:
def extension_whitelist
%w(jpg jpeg gif png)
end
# Override the filename of the uploaded files:
# Avoid using model.id or version_name here, see uploader/store.rb for details.
def filename
return unless original_filename
contenttype = original_filename.split('.').last
"avatar.#{contenttype}"
end
end
nginx 配置
server {
listen 443 ssl;
server_name example.com;
....
ssl stuff
....
location / {
proxy_read_timeout 150;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://backend:3000;
}
}
如果我将以下行放入 neginx 配置(如在 stackoverflow 上推荐 100 次)...
error_page 405 =200 $uri;
...服务器抛出错误:
Can not read property 'attributes' of undefined
此错误消息来自 dropzone。它无法完成上传。在 Rails 中什么都没有收到,日志中没有条目,什么都没有......
更新和解决方案 最后我修好了。问题是 Handlebars 中的 uploadURL 错误。本地它使用这个错误的 url,因为它是一个相对路径。但在生产中需要一条绝对路径。
【问题讨论】:
-
关于容器的内容太多了,前端没有。如果您包含一些有关用于将文件从 ember 上传到服务器的插件或代码的简短信息,那就太好了。你检查你的前端是否发送文件?也许不是。您应该使用开发工具(Chrome 中的 Ctrl+Shift+I),“网络”选项卡。
-
405 是“不支持的方法”。发送端很可能有问题。你也应该避免像
error_page 405 =200 $uri;这样的技巧。它只是告诉网络服务器“如果发生 405 错误,将状态更改为 200 并继续”。在实际项目中这样做是错误的。 -
刚刚注意到“请求详细信息”链接。您使用 PATCH 方法,这很可能是 nginx 不支持的。您应该找到一种将方法更改为 POST 的方法(在您的 ember 应用程序中)。不能给出更详细的答案,因为我不知道你用什么来上传。如果是this dropzone,向组件添加 method="post" 参数应该会有所帮助
-
ember-cli-dropzonejs 是我使用的插件。我使用 PATCH,因为我使用文件上传向用户添加头像。所以 PATCH 转到用户控制器中的 /users/:id 路径。那是错误的方式吗?我是否必须添加一个额外的端点来上传文件,并在额外的步骤中将此上传的路径添加到用户模型?
-
我也将 CORS 选项放到了 nginx 配置中,如下所示: location / { # add_header 'Access-Control-Allow-Origin' *; if ($cors = "true") { add_header 'Access-Control-Allow-Origin' "$http_origin"; add_header 'Access-Control-Allow-Methods' 'GET、OPTIONS、POST、DELETE、PUT、PATCH'; add_header '访问控制允许凭据' 'true'; add_header 'Access-Control-Allow-Headers' '用户代理,保持活动,内容类型'; } ... } 但这仍然不是问题的解决方案。
标签: ruby-on-rails nginx ember.js docker imagemagick