This issue has been bothering me for many hours and I can't seem to find a solution to it.

这个问题困扰了我好几个小时,我似乎找不到解决的办法。

I have a rails 3.2 app that allows users to upload files to an Amazon S3 account using carrierwave_direct, fog, and carrierwave (dependency for carrierwave_direct). Using carrierwave_direct allows the user to skip uploading the file to the server by POSTing it directly to Amazon S3 (saves server processing and timeouts like Heroku for large files).

我有一个rails 3.2应用,允许用户使用carrierwave_direct、fog和carrierwave (carrierwave_direct的依赖项)将文件上传到Amazon S3帐户。使用carrierwave_direct,用户可以将文件直接发布到Amazon S3,从而跳过将文件上载到服务器的过程(对于大型文件,可以保存服务器处理和Heroku等超时)。

It works fine if all you do is select 1 file, upload it to Amazon, and want a redirect_to a URL you provide Amazon. It does this by POSTing the form to Amazon S3, and Amazon responds to a provided URL (you specify this URL in your form) with some params in the URL, which are then stored as a pointer to the file on Amazon in your model.

如果您所做的只是选择1文件,将其上传到Amazon,并希望将redirect_to您提供的Amazon URL。它通过将表单发布到Amazon S3,然后Amazon响应一个提供的URL(您在表单中指定这个URL)和URL中的一些params,然后在您的模型中作为指向Amazon文件的指针存储。

So the lifecycle is: select 1 file, POST to Amazon, Amazon responds with a URL that sends you to another page, and you can then save a record with a pointer to the Amazon file.

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

What I've been trying to figure out is how do I allow multiple files to be selected and uploaded and update the upload progress? I'm trying to do this with pure javascript (using the file API provided by modern browsers) so I don't want any 3rd party tools. Also, in the pursuit of learning this in-depth, I'm avoiding any plugins and am trying to write the code myself.

我一直想弄明白的是,如何让多个文件被选中并上传并更新上传进度?我尝试使用纯javascript(使用现代浏览器提供的文件API)来实现这一点,因此我不希望使用任何第三方工具。此外,为了深入学习,我避免使用任何插件,并尝试自己编写代码。

The functionality I'm trying to obtain is:

我试图获得的功能是:

  1. User sees form with file field (or drag/drop)
  2. 用户通过文件字段查看表单(或拖/删除)
  3. User selects multiple files (either click file field or drag/drop)
  4. 用户选择多个文件(单击file字段或拖放)
  5. Using Javascript (no servers yet), build a queue of selected files to upload (just filename and size, using browser File API)
  6. 使用Javascript(还没有服务器),构建一个选定文件的队列来上载(使用浏览器文件API,仅使用文件名和大小)
  7. User then clicks a "begin Upload" button
  8. 用户点击“开始上传”按钮
  9. Iterate over each file in queue and POST the file to Amazon S3; Amazon will respond to each individual POST with a URL and that URL needs to be handled via Javascript, not as a standard request; the URL provided by Amazon will create a record that stores the pointer to the Amazon file; once the record has been created, the code goes to the next file in the queue until finished.
  10. 遍历队列中的每个文件并将该文件发布到Amazon S3;Amazon将使用一个URL对每个单独的POST进行响应,该URL需要通过Javascript来处理,而不是作为标准请求;Amazon提供的URL将创建一个记录来存储指向Amazon文件的指针;创建记录后,代码将转到队列中的下一个文件,直到完成。

At this point, I could even do without an individual progress bar; I'd be happy just to get multiple files POSTed to Amazon S3 without page refreshes.

在这一点上,我甚至可以不使用单独的进度条;我很高兴能在没有刷新页面的情况下将多个文件发布到Amazon S3。

I am not partial to any of the gems. I'm actually afraid I'm going to have to write what I want to do from scratch if I really want it done in a specific way. The goal is multiple file uploads to an Amazon S3 account via AJAX. I would be ecstatic with even general concepts of how to approach the problem. I've spent many hours googling this and I just haven't found any solutions that do what I want. Any help at all would be greatly appreciated.

我不喜欢任何宝石。实际上,如果我真的想用一种特定的方式来完成,我恐怕得从头开始写我想做的事情。目标是通过AJAX将多个文件上传到Amazon S3帐户。我甚至对如何解决这个问题的一般概念都感到欣喜若狂。我已经在谷歌上搜索了好几个小时了,但是我还没有找到任何解决方案来实现我的愿望。如有任何帮助,我们将不胜感激。

EDIT 2014-03-02

编辑2014-03-02

Raj asked how I implemented my multiple upload. It's been so long I don't recall all the "why" behind what I did (probably bad code anyway as it was my first time), but here is what I had going on.

Raj问我是如何实现多重上传的。这么长时间以来,我都不记得我所做的事情背后的“为什么”了(不管怎么说,这可能是我第一次做的糟糕的代码),但我所做的事情是这样的。

The model I was uploading was a Testimonial, which has an associated image being stored in Amazon S3. It allowed a user to select multiple images (I think they were actually PDF files I converted to images) and drag/drop them onto the screen. While uploading, I displayed a modal that gave the user feedback about how long it would take.

我上传的模型是一个证明,它有一个相关的图像存储在Amazon S3中。它允许用户选择多个图像(我认为它们实际上是我转换成图像的PDF文件),并将它们拖放到屏幕上。在上传的时候,我展示了一个模式,给用户反馈要花多长时间。

I don't pretend to remember what I was doing on a lot of this, but if it helps feel free to use it.

我不会假装记得我在很多事情上做了什么,但如果它能让你自由地使用它。

# Gemfile
# For client-side multiple uploads
gem "jquery-fileupload-rails"

# For file uploads and Amazon S3 storage
gem "rmagick"
gem "carrierwave"
gem "fog"

Here's the 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>

And the JS:

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)

The Testimonial model:

证明模型:

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

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

2 个解决方案

#1


6

As advised in comment, use jQuery Upload: http://blueimp.github.com/jQuery-File-Upload/

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

更多相关文章

  1. 使用ajax请求上传文件[副本]
  2. 使用JQuery从外部文件中通过id选择器获取html内容
  3. GET ajax请求发送到同一个php文件
  4. 无法使用jquery发送简单的ajax请求来获取json文件
  5. 在上传前预览xls、xlsx、doc等文件的缩略图
  6. 静态h5页面没有后台直接访问本地json文件
  7. Mvc 5和实体框架6中的Jquery多文件上载问题
  8. 单击文件输入后,Fancybox正在关闭
  9. Struts2 使用Jquery+ajax 文件上传

随机推荐

  1. Java中字符流和字节流到底有什么区别!!!
  2. 5个java面试题。。。请高手给个答案。。
  3. java中匹配字符串中的中文字符(含中文标
  4. Java nio 学习笔记(一) Buffer(缓冲区)与Chan
  5. 如何知道Object是否为String类型对象?
  6. Java实现图像对比类
  7. Eclipse Juno 4.2的Swing插件[重复]
  8. 关于JAVA类加载大家发表一下见解吧
  9. Java标准标签库学习小结
  10. Javascript实现页面加载完成后自动刷新一