Dan*_*n L 5 jquery file-upload ruby-on-rails amazon-s3 ruby-on-rails-3
这个问题困扰了我好几个小时,我似乎无法找到解决方案.
我有一个rails 3.2应用程序,允许用户使用carrierwave_direct,fog和carrierwave(对carrierwave_direct的依赖)将文件上传到Amazon S3帐户.使用carrierwave_direct允许用户通过将文件直接发送到Amazon S3来跳过将文件上传到服务器(保存服务器处理和Heroku等大文件的超时).
如果您只是选择1个文件,将其上传到亚马逊,并希望重定向到您提供亚马逊的URL,它就可以正常工作.它通过将表单发布到Amazon S3来执行此操作,并且Amazon使用URL中的一些参数响应提供的URL(您在表单中指定此URL),然后将其存储为模型中Amazon上的文件的指针.
所以生命周期是:选择1个文件,POST到亚马逊,亚马逊用一个URL回复你的另一个页面,然后你可以保存一个带有指向亚马逊文件的指针的记录.
我一直想弄清楚的是如何选择和上传多个文件并更新上传进度?我正在尝试使用纯javascript(使用现代浏览器提供的文件API)这样做,所以我不想要任何第三方工具.另外,在深入学习这个问题的过程中,我正在避免使用任何插件,并且我正在尝试自己编写代码.
我想要获得的功能是:
在这一点上,我甚至可以没有个人进度条; 我很乐意在没有页面刷新的情况下将多个文件发布到Amazon S3.
我并不偏爱任何宝石.我实际上害怕如果我真的希望以特定方式完成它,我将不得不从头开始写我想做的事情.目标是通过AJAX将多个文件上传到Amazon S3帐户.即使是如何处理问题的一般概念,我也会欣喜若狂.我花了很多时间在谷歌搜索这个,我还没有找到任何可以做我想要的解决方案.任何帮助都将非常感激.
编辑2014-03-02
Raj询问我是如何实现多重上传的.这已经很久了,我不记得我所做的所有"为什么"(可能是糟糕的代码,因为这是我第一次),但这就是我的目标.
我上传的模型是推荐书,其中相关图像存储在Amazon S3中.它允许用户选择多个图像(我认为它们实际上是我转换为图像的PDF文件)并将它们拖放到屏幕上.在上传时,我显示了一个模式,向用户提供有关需要多长时间的反馈.
我不会假装记住我在很多方面所做的事情,但如果它有助于随意使用它.
# Gemfile
# For client-side multiple uploads
gem "jquery-fileupload-rails"
# For file uploads and Amazon S3 storage
gem "rmagick"
gem "carrierwave"
gem "fog"
Run Code Online (Sandbox Code Playgroud)
这是观点:
# app/views/testimonials/new.html.erb
<div id="main" class="padded">
<div class="center">
<div id="dropzone">
Click or Drop Files here to Upload
</div>
<%= form_for @testimonial do |f| %>
<div class="field">
<%= file_field_tag :image, multiple: true, name: "testimonial[image]", id: "testimonial_image" %>
</div>
<% end %>
</div>
</div>
<div id="mask"></div>
<div id="modal">
<h1>
Uploading <span id="global-upload-count">0</span> Files...
</h1>
<div id="global-progress">
<div id="global-progress-bar" style="width: 0%">
<div id="global-progress-percentage">0%</div>
</div>
</div>
<div id="global-processing">
<span class="spinner"></span> Processing...<span id="global-processing-count">0</span> sec
</div>
</div>
<script id="template-upload" type="text/x-tmpl">
<div class="upload">
{%=o.name%} ({%=o.readable_size%})
<div class="float-right percentage"></div>
<div class="progress"><div class="bar" style="width: 0%"></div></div>
</div>
</script>
Run Code Online (Sandbox Code Playgroud)
和JS:
number_to_human_size = (bytes) ->
sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']
i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)))
return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i]
dropzone_hover = (e) ->
e.preventDefault()
$(this).addClass("dropzone-hover")
dropzone_leave = (e) ->
e.preventDefault()
$(this).removeClass("dropzone-hover")
jQuery ->
global_count = 0
seconds_to_process = 0
processing_factor = 5 # seconds to convert/process each uploaded file
$("#testimonial_image").hide()
dropzone = $("#dropzone")
dropzone.bind "click", (e) ->
$("#testimonial_image").click()
dropzone.bind("dragover", dropzone_hover)
dropzone.bind("dragleave", dropzone_leave)
dropzone.bind("drop", dropzone_leave)
$("#new_testimonial").data("global-count", "0")
$("#new_testimonial").fileupload
dropZone: $("#dropzone")
maxFileSize: 5000000 # 5 MB
dataType: "script"
add: (e, data) ->
file = data.files[0]
file.readable_size = number_to_human_size(file.size)
data.context = $(tmpl("template-upload", file).trim())
$("#new_testimonial").append(data.context)
data.submit()
global_count += 1
progress: (e, data) ->
if data.context
progress = parseInt(data.loaded / data.total * 100, 10)
data.context.find(".bar").css("width", progress + "%")
data.context.find(".percentage").text(progress + "%")
submit: (e, data) ->
$("#mask").show()
$("#modal").center().show()
progressall: (e, data) ->
$("#global-upload-count").text(global_count)
global_progress = parseInt(data.loaded / data.total * 100, 10)
$("#global-progress-bar").css("width", global_progress + "%")
$("#global-progress-percentage").text(global_progress + "%")
if global_progress >= 100
seconds_to_process = global_count * processing_factor
$("#global-processing-count").text(seconds_to_process)
$("#global-processing").show()
timer = setInterval(->
seconds_to_process = seconds_to_process - 1
$("#global-processing-count").text(seconds_to_process)
if seconds_to_process == 0
clearInterval(timer)
global_count = 0
seconds_to_process = 0
$("#modal, #mask").hide(0)
, 1000)
Run Code Online (Sandbox Code Playgroud)
推荐模型:
class Testimonial < ActiveRecord::Base
mount_uploader :image, ImageUploader
def display_name
if name.blank?
return "Testimonial #{self.id}"
else
return name
end
end
end
Run Code Online (Sandbox Code Playgroud)
正如评论中所建议的,使用jQuery上传:http://blueimp.github.com/jQuery-File-Upload/