我需要在我的Rails 3应用程序上使用一个界面将多个文件上传到Amazon S3(因为我在heroku上),可能还有进度条。
我已经轻松管理了如何设置回形针和上传单个文件,但我现在真的迷失了如何继续前进。
请你给我一些建议吗?这是我在互联网上搜索的2天,但我找不到可行的解决方案
**编辑**
我真的无法理解......我生气了,因为我已经失去了太多时间......请帮助我。 如果我尝试打开Johnny引用的示例应用程序,我只能得到这个(在我的应用程序中它是相同的):
用户界面在哪里? 我的浏览器有什么问题吗?
**编辑2 **
Here on GitHub you can find my testapp ...请你能解释一下为什么该死的上传用户界面没有出现?谢谢!
**编辑3 **
非常感谢Johnny,我不知道jquery和原型不能共存的事实。 现在插件正确显示,但是尝试上传它会创建一个新的“上传”记录,但其附件字段为空,文件不在s3上。
这是控制台所说的:
Started POST "/uploads" for 127.0.0.1 at 2011-06-27 16:17:22 +0200
Processing by UploadsController#create as JSON
Parameters: {"utf8"=>"✓", "authenticity_token"=>"GesRBTiZR1f2LV/bAeAdxWqF++gxcDJw4pPGStYGsH8=", "upload"=>{"attachment"=>[#<ActionDispatch::Http::UploadedFile:0x000001032834b8 @original_filename="animal-tiger-66550.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"upload[attachment][]\"; filename=\"animal-tiger-66550.jpg\"\r\nContent-Type: image/jpeg\r\n", @tempfile=#<File:/var/folders/Qj/QjEqvUUNGTmuki5SXOaaG++++TI/-Tmp-/RackMultipart20110627-1818-1syiex9>>]}}
AREL (0.5ms) INSERT INTO "uploads" ("attachment", "created_at", "updated_at", "attachment_file_name", "attachment_content_type", "attachment_file_size", "attachment_updated_at") VALUES (NULL, '2011-06-27 14:17:23.049136', '2011-06-27 14:17:23.049136', NULL, NULL, NULL, NULL)
[paperclip] Saving attachments.
Completed 200 OK in 64ms (Views: 4.2ms | ActiveRecord: 0.7ms)
答案 0 :(得分:5)
你可以看一下jQuery-File-Upload。演示here和rails 3 / Paperclip设置here。
编辑:正如@apneadiving所提到的,该库已更新为版本5.您拥有的脚本适用于版本4.您应尝试修改this以使用PaperClip。将大部分示例代码复制粘贴到我的应用程序中(稍作修改)对我有用:
#app/public/javascripts/application.js
$(function () {
// Initialize the jQuery File Upload widget:
$('#fileupload').fileupload();
// Load existing files:
$.getJSON($('#fileupload form').prop('action'), function (files) {
var fu = $('#fileupload').data('fileupload');
fu._adjustMaxNumberOfFiles(-files.length);
fu._renderDownload(files)
.appendTo($('#fileupload .files'))
.fadeIn(function () {
// Fix for IE7 and lower:
$(this).show();
});
});
// Open download dialogs via iframes,
// to prevent aborting current uploads:
$('#fileupload .files a:not([target^=_blank])').live('click', function (e) {
e.preventDefault();
$('<iframe style="display:none;"></iframe>')
.prop('src', this.href)
.appendTo('body');
});
});
#app/controllers/uploads_controller.rb
def create
@upload = Upload.new(params[:upload])
if @upload.save
render :json => [{
:pic_path => @upload.attachment.url.to_s ,
:name => @upload.attachment.instance.attributes["picture_file_name"]
}], :content_type => 'text/html'
else
render [:json => { :result => 'error'}], :content_type => 'text/html'
end
end
#app/views/uploads/new.html.haml
%link#theme{:href => "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/themes/base/jquery-ui.css", :rel => "stylesheet"}
= stylesheet_link_tag 'jquery.fileupload-ui'
#fileupload
= form_for Upload.new, :html => { :multipart => true } do |f|
.fileupload-buttonbar
%label.fileinput-button
%span Add files...
= f.file_field :attachment, :multiple => true
%button.start{:type => "submit"} Start upload
%button.cancel{:type => "reset"} Cancel upload
%button.delete{:type => "button"} Delete files
.fileupload-content
%table.files
.fileupload-progressbar
%script#template-upload{:type => "text/x-jquery-tmpl"}
%tr{:class => "template-upload{{if error}} ui-state-error{{/if}}"}
%td.preview
%td.name ${name}
%td.size ${sizef}
{{if error}}
%td.error{:colspan => "2"}
Error:
{{if error === 'custom_failure'}}Custom Error Message
{{else}}${error}
{{/if}}
{{else}}
%td.progress
%div
%td.start
%button Start
{{/if}}
%td.cancel
%button Cancel
%script#template-download{:type => "text/x-jquery-tmpl"}
%tr{:class => "template-download{{if error}} ui-state-error{{/if}}"}
{{if error}}
%td
%td.name ${name}
%td.size ${sizef}
%td.error{:colspan => "2"}
Error:
{{if error === 1}}File exceeds upload_max_filesize (php.ini directive)
{{else}}${error}
{{/if}}
{{else}}
%td.preview
{{if thumbnail_url}}
%a{:href => "${url}", :target => "_blank"}
%img{:src => "${thumbnail_url}"}/
{{/if}}
%td.name
<a href="${url}"{{if thumbnail_url}} target="_blank"{{/if}}>${name}
%td.size ${sizef}
%td{:colspan => "2"}
{{/if}}
%td.delete
%button{"data-type" => "${delete_type}", "data-url" => "${delete_url}"} Delete
修改强> 快速浏览一下你的应用程序,问题是你是用jquery混合原型。最简单的方法是使用jquery-rails切换到jQuery。
#Gemfile
gem 'jquery-rails'
接下来,运行bundle install
,然后rails g jquery:install
。
然后将app/views/layouts/application.erb
更改为此:
<%= stylesheet_link_tag :all %>
<%= csrf_meta_tag %>
<%= javascript_include_tag 'jquery.min' %>
<%= javascript_include_tag 'jquery-ui-1.8.13.custom.min' %>
<%= javascript_include_tag 'jquery.tmpl.min' %>
<%= javascript_include_tag 'jquery.iframe-transport' %>
<%= javascript_include_tag 'jquery.fileupload' %>
<%= javascript_include_tag 'jquery.fileupload-ui' %>
<%= javascript_include_tag 'jquery_ujs' %>
<%= javascript_include_tag 'application' %>
请注意,我删除了
<%= javascript_include_tag :defaults %>
这样我就可以指定加载jquery,jquery_ujs和应用程序的顺序。
答案 1 :(得分:1)
我最近开始执行一项非常类似的任务,swf plugin(至少是最近的那个)确实会让你更新回形针的记录。它有几乎所有你需要扩展的回调。
:onUploadComplete (upload_options,event)
这是Nathan Colgate关于此事的gist。他只是在完成上传后对rails服务器进行远程调用,告诉它有关回形针附件的位置。
来自他的uploadCompleteHandler
var uploadCompleteHandler = function(upload_options,event){
$.ajax({
url: '<%= notify_rails_of_successful_upload_path(:format => :js)%>',
global: false,
type: 'POST',
data: ({
'authenticity_token' : '<%= form_authenticity_token %>',
'upload' : {
'file_file_name' : upload_options.FileName,
'file_file_size' : upload_options.FileSize,
'file_content_type' : upload_options.ContentType
}
}),
dataType: 'script'
}
)
};
我不确定是否会为每个文件触发这个确切的回调;它看起来确实如此。但他通过ajax请求将所有回形针需求传回去。文件名,大小,内容类型。通过这种方式,所有发送到heroku的文本都是关于文件的一些文本,通过将应用程序提供给客户端来节省大量工作。
编辑:flash是我发现避免通过heroku向s3发送大量数据的唯一方法。有一些html5 / js-up上传器可能能够完成工作,但我发现的那些在开发树上仍然非常成熟。
答案 2 :(得分:0)
Paperclip & multiple files upload,虽然不是S3特定的。
答案 3 :(得分:0)
查看:(注意数组blog_post[avatars][]
)
<form accept-charset="UTF-8" action="/blog_posts" enctype="multipart/form-data" id="new_blog_post" method="post">
<div style="margin:0;padding:0;display:inline">
<input name="utf8" type="hidden" value="✓" />
<input name="authenticity_token" type="hidden" value="<%=form_authenticity_token %>" />
</div>
<p><input id="blog_post" name="blog_post[avatars][]" type="file" multiple /></p>
<p><input name="commit" type="submit" value="Upload" /></p>
</form>
控制器:
# POST /blog_posts
# POST /blog_posts.json
def create
@blog_post = BlogPost.new(params[:blog_post])
@blog_post.avatars.each do |avatar|
each_blog_post = BlogPost.new
each_blog_post.avatar = avatar
if each_blog_post.save
end
end
end
型号:
class BlogPost < ActiveRecord::Base
attr_accessible :title, :avatar, :avatars
has_attached_file :avatar
attr_accessor :avatars
end