gpt4 book ai didi

jquery - 使用 Rails 3.2 和 AJAX 将多个文件直接上传到 Amazon S3(非闪存上传解决方案)

转载 作者:行者123 更新时间:2023-12-03 23:02:50 25 4
gpt4 key购买 nike

这个问题已经困扰我好几个小时了,但我似乎找不到解决方案。

我有一个 Rails 3.2 应用程序,允许用户使用 Carrierwave_direct、Fog 和 Carrierwave(CarrierWave_direct 的依赖项)将文件上传到 Amazon S3 帐户。使用 Carrierwave_direct 允许用户通过直接将文件 POST 到 Amazon S3 来跳过将文件上传到服务器的过程(节省服务器处理和超时,如处理大文件的 Heroku)。

如果您所做的只是选择 1 个文件,将其上传到 Amazon,并希望重定向到您向 Amazon 提供的 URL,则效果很好。它通过将表单发布到 Amazon S3 来实现此目的,然后 Amazon 使用 URL 中的一些参数响应提供的 URL(您在表单中指定此 URL),然后将这些参数存储为指向模型中 Amazon 上的文件的指针。

因此生命周期是:选择 1 个文件,POST 到 Amazon,Amazon 响应一个 URL,将您发送到另一个页面,然后您可以使用指向 Amazon 文件的指针保存记录。

我一直想弄清楚的是如何允许选择并上传多个文件并更新上传进度?我正在尝试使用纯 JavaScript(使用现代浏览器提供的文件 API)来完成此操作,所以我不需要任何第三方工具。另外,为了深入学习,我避免使用任何插件并尝试自己编写代码。

我想要获得的功能是:

  1. 用户看到带有文件字段(或拖放)的表单
  2. 用户选择多个文件(单击文件字段或拖/放)
  3. 使用 Javascript(尚无服务器)构建要上传的选定文件队列(仅文件名和大小,使用浏览器文件 API)
  4. 然后用户点击“开始上传”按钮
  5. 迭代队列中的每个文件并将文件 POST 到 Amazon S3;亚马逊将使用 URL 响应每个单独的 POST,并且该 URL 需要通过 Javascript 处理,而不是作为标准请求; Amazon 提供的 URL 将创建一条记录,存储指向 Amazon 文件的指针;创建记录后,代码将转到队列中的下一个文件,直到完成。

此时,我什至可以不用单独的进度条;我很乐意将多个文件发布到 Amazon S3 而无需刷新页面。

我不偏爱任何 gem 。事实上,我担心如果我真的想以特定的方式完成它,我将不得不从头开始写下我想做的事情。目标是通过 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"

这是 View :

# 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>

还有 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)

推荐模型:

class Testimonial < ActiveRecord::Base
mount_uploader :image, ImageUploader

def display_name
if name.blank?
return "Testimonial #{self.id}"
else
return name
end
end
end

最佳答案

根据评论中的建议,使用 jQuery 上传:http://blueimp.github.com/jQuery-File-Upload/

关于jquery - 使用 Rails 3.2 和 AJAX 将多个文件直接上传到 Amazon S3(非闪存上传解决方案),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11597784/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com