我对gem s3_direct_upload有困难。毫无疑问,我遵循了这些精彩的教程并没有取得任何成果:
http://www.blitztheory.com/direct-upload-with-s3_direct_upload/
http://blog.littleblimp.com/post/53942611764/direct-uploads-to-s3-with-rails-paperclip-and
宝石:' aws-sdk',' s3_direct_upload',' activeadmin',' paperclip'
Ruby:2.1.2,Rails:4.1.4
似乎脚本无法正常工作,当我放在那里时,某些文件没有出现进度条,在日志中没有请求被发送,即使我看了firefox控制台。那么我应该怎么做才能使这项工作?
以下是我的文件:
# config/schema.rb
ActiveRecord::Schema.define(version: 20140906145459) do
....
create_table "images", force: true do |t|
t.datetime "created_at"
t.datetime "updated_at"
t.string "photo_file_name"
t.string "photo_content_type"
t.integer "photo_file_size"
t.datetime "photo_updated_at"
t.integer "gallery_id"
t.string "title"
t.string "photo_file_path"
t.string "direct_upload_url"
end
end
# app/models/image.rb
class Image < ActiveRecord::Base
belongs_to :gallery
acts_as_taggable
has_attached_file :photo,
:styles => { :small => '300x300>', :medium => '800x800>' },
:default_url => "images/:style/missing.png"
validates_attachment_content_type :photo, :content_type => /\Aimage\/.*\Z/
def self.copy_and_delete(paperclip_file_path, raw_source)
s3 = AWS::S3.new #create new s3 object
destination = s3.buckets[Rails.configuration.aws['bucket']].objects[paperclip_file_path]
sub_source = CGI.unescape(raw_source)
sub_source.slice!(0) # the attached_file_file_path ends up adding an extra "/" in the beginning. We've removed this.
source = s3.buckets[Rails.configuration.aws['bucket']].objects["#{sub_source}"]
source.copy_to(destination) #copy_to is a method originating from the aws-sdk gem.
source.delete #delete temp file.
end
end
# app/admin/image.rb
ActiveAdmin.register Image do
form partial: "form"
controller do
def create
if (params[:image][:attached_file_path])
@image = Image.new(image_params)
@gallery = Gallery.find(1)
@gallery.images << @image
respond_to do |format|
if @image.save!
paperclip_file_path = "images/photo/#{id_partition @image.id}/original/#{params[:image][:photo_file_name]}"
raw_source = params[:image][:photo_file_path]
Image.copy_and_delete paperclip_file_path, raw_source
format.html { redirect_to admin_image_path(@image), notice: 'Image was successfully created.' }
format.json { render :index, status: :created, location: @gallery }
else
format.html { render :new }
format.json { render json: @article.errors, status: :unprocessable_entity }
end
end
else
@image = Image.new
render action: 'new', notice: "No file"
end
end
end
end
# app/views/admin/images/_form.html.erb
<%= s3_uploader_form callback_url: admin_images_url,
callback_param: "image[direct_upload_url]",
id: "s3-uploader" do %>
<%= file_field_tag :file, multiple: false %>
<% end %>
<div id="uploads_container"></div>
<script id="template-upload" type="text/x-tmpl">
<div id="file-{%=o.unique_id%}" class="upload">
{%= o.name %}
<div class="progress"><div class="bar" style="width: 0%"></div></div>
</div>
</script>
<br />
<%= semantic_form_for [:admin, @image] do |f| %>
<%if @image.errors.any? %>
<ul>
<% @image.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
<%= f.inputs do %>
<%= f.input :title %>
<%= f.input :tag_list, hint: "Указывайте теги через запятую" %>
<%= f.hidden_field :direct_upload_url %>
<%= f.hidden_field :photo_file_name %>
<%= f.hidden_field :photo_file_size %>
<%= f.hidden_field :photo_content_type %>
<%= f.hidden_field :photo_file_path %>
<% end %>
<%= f.actions %>
<% end %>
# config/initializers/active_admin.rb
ActiveAdmin.setup do |config|
config.register_javascript 's3_direct_upload.js'
config.register_javascript 'direct_upload.js'
end
# app/assets/javascripts/direct_upload.js.coffee
jQuery ->
$("#s3_uploader").S3Uploader
remove_completed_progress_bar: false
remove_failed_progress_bar: true
progress_bar_target: $("#uploads_container")
allow_multiple_files: false
$("#s3_uploader").bind "s3_uploads_start", (e) ->
alert("Upload started")
$("#s3_uploader").bind "s3_upload_failed", (e, content) ->
alert content.filename + " failed to upload."
$("#s3_uploader").bind "s3_upload_complete", (e, content) ->
alert "Upload complete."
$("#image_direct_upload_url").val(content.url);
$("#image_photo_file_name").val(content.filename);
$("#image_photo_file_path").val(content.filepath);
$("#image_photo_file_size").val(content.filesize);
$("#image_photo_file_type").val(content.filetype);
$('#s3_uploader').bind "ajax:success", (e, data) ->
alert("server was notified of new file on S3; responded with '#{data}")
# config/initializers/aws.rb
require 'aws-sdk'
Rails.configuration.aws =
YAML.load(ERB.new(
File.read("#{Rails.root}/config/amazon_aws.yml")
).result)[Rails.env].symbolize_keys!
# config/initializers/paperclip.rb
Paperclip::Attachment.default_options.merge!(
url: ':s3_domain_url',
path: '/:class/:attachment/:id_partition/:style/:filename',
s3_permissions: {
original: :private
},
storage: :s3,
s3_credentials: Rails.configuration.aws #config/initializers/aws.rb
)
# config/initializers/s3_direct_upload.rb
S3DirectUpload.config do |c|
c.access_key_id = Rails.configuration.aws[:access_key_id]
c.secret_access_key = Rails.configuration.aws[:secret_access_key]
c.bucket = Rails.configuration.aws[:bucket]
c.region = nil
c.url = nil
end
# config/amazon_aws.yml
defaults: &defaults
access_key_id: "..."
secret_access_key: "..."
development:
<<: *defaults
bucket: "..."
test:
<<: *defaults
bucket: "..."
production:
access_key_id: <%= ENV["ACCESS_KEY_ID"]%>
secret_access_key: <%= ENV["SECRET_ACCESS_KEY"] %>
bucket: <%= ENV["S3_BUCKET_NAME"] %>
提前致谢。
更新
CORS配置:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
更新2
我试图做各种各样的事情,比如googing on enable javascripts或写下应该总是显示的警告信息,但是一切都没有结果。我做的最后一件事是使用paperclip + s3_direct_upload创建简单的应用程序...出现了条形图,应用程序试图上传到s3。现在我累了。绝对是app的错误。或者ActiveAdmin。明天会尝试。
答案 0 :(得分:2)
这是我无意中搞砸了一切。首先是在js文件中:
#= require active_admin/base
#= require s3_direct_upload
jQuery ->
$("#s3-uploader").S3Uploader
remove_completed_progress_bar: false
progress_bar_target: $("#uploads_container")
allow_multiple_files: false
$("#s3-uploader").bind "s3_upload_complete", (e, content) ->
alert "Upload complete."
$("#image_direct_upload_url").val content.url
$("#image_photo_file_name").val content.filename
$("#image_photo_file_path").val content.filepath
$("#image_photo_file_size").val content.filesize
我将与s3Uploader相关的代码放在activeadmin.js.coffee中,并用(和#34;#s3_uploader&#34;)中的下划线替换了我的表单中的连字符:
<%= s3_uploader_form callback_url: admin_images_url, callback_param: "direct_upload_url", id: "s3-uploader" do %>
<%= file_field_tag :file, multiple: false %>
<% end %>
另请注意,在callback_url中我使用了admin_images_url,因为它的控制器应该处理这个问题。
但那并不是每次都有效......在测试应用程序中一切都很好,但不是在我的主应用程序中。问题发生在amazon_aws.yml。我删除了access_key_id和secret_access_key周围错误放置的引号,并发送了POST请求。
但是,由于控制器,图像无法正常保存。使用activeadmin我这样做了:
ActiveAdmin.register Image do
permit_params :title, :tag_list, :direct_upload_url, :photo_file_name, :photo_file_size, :photo_content_type, :photo_file_path
form partial: "form"
controller do
def create
if params[:url]
@image = Image.new
render "new" and return
end
if (params[:image][:photo_file_path])
@image = Image.new(permitted_params[:image])
@gallery = Gallery.find(1)
@gallery.images << @image
respond_to do |format|
if @image.save!
paperclip_file_path = "images/photos/#{Paperclip::Interpolations.id_partition( @image.photo, "photo" )}/original/#{params[:image][:photo_file_name]}"
raw_source = params[:image][:photo_file_path]
Image.copy_delete_preprocess_save paperclip_file_path, raw_source, @image.id
format.html { redirect_to admin_image_path(@image), notice: 'Image was successfully created.' }
format.json { render :index, status: :created, location: @gallery }
else
format.html { render :new }
format.json { render json: @article.errors, status: :unprocessable_entity }
end
end
else
@image = Image.new
render action: 'new', notice: "No file"
end
end
end
end
然后我在Image model中更改了方法copy_delete_preprocess_save:
def self.copy_delete_preprocess_save(paperclip_file_path, raw_source, id)
s3 = AWS::S3.new #create new s3 object
destination = s3.buckets[Rails.configuration.aws[:bucket]].objects[paperclip_file_path]
sub_source = CGI.unescape(raw_source)
sub_source.slice!(0) # the attached_file_file_path ends up adding an extra "/" in the beginning. We've removed this.
source = s3.buckets[Rails.configuration.aws[:bucket]].objects["#{sub_source}"]
obj = source.copy_to(destination) #copy_to is a method originating from the aws-sdk gem and store returned object for preprocessing.
source.delete #delete temp file.
image = Image.find(id)
image.photo = obj.url_for(:get)
image.photo_file_path = nil
image.save!
end
另外我应该提到serious_c0der建议的补丁。谢谢。
而且,作为一种神化,我在active_admin.css.scss中添加了这个字符串,可以看到进度条:
@import "s3_direct_upload_progress_bars";
感谢您的帮助。希望它可以帮助别人。
答案 1 :(得分:1)
我也遇到了s3_direct_upload
gem的问题,我的问题与你的问题类似,问题与S3 Buckets的URL模式有关。这是我的步骤的回顾,帮助我解决了我的问题。
要进行调试,请按以下步骤操作:
克隆此回购:s3_direct_upload_example
创建新的测试存储区并设置以下CORS
配置:
<CORSConfiguration>
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
将您的AWS
凭据导出到环境:
$ export AWS_S3_BUCKET=your-bucket-name
$ export AWS_ACCESS_KEY_ID=your-aws-access-key-id
$ export AWS_SECRET_ACCESS_KEY=your-aws-secret-access-key
bundle
,运行rails s
并转到http://0.0.0.0:3000
查看上传是否有效。
如果上传 正在运行,请在s3_direct_upload.rb
中注释掉该补丁,否则可能是您的Bucket或AWS凭据存在问题。< / p>
重新启动rails服务器:
如果上传停止工作 ,您还需要将 Monkey Patch 应用到您的应用中,问题出在宝石无法形成正确的网址。
如果上传仍然有效 ,则问题在于应用中的代码。
答案 2 :(得分:0)
我是那个写过你所链接的第一个教程的人。我会尽力帮助你完成这件事。在direct_upload.js.coffee中,理想情况下,您的错误消息应该触发,并让您知道如果您的CORS设置正确,会发生什么。我怀疑您没有正确设置S3存储桶上的Cross Origin(CORS)设置。请完成该步骤,因为我认为S3从一开始就拒绝了您的请求。