繁体   English   中英

Rails - Paper_Clip - 支持多文件上传

[英]Rails - Paper_Clip - Support for Multi File Uploads

我在我的Rails 3应用程序上安装了paper_clip,并且可以上传文件 - 哇这很有趣而且简单!

现在的挑战是,允许用户上传多个对象。 是否单击选择文件并能够选择多个文件。 或者单击更多按钮并获取另一个文件上载按钮。

我无法找到任何教程或宝石来支持这种开箱即用。 令人震惊我知道......

任何建议或解决方案。 似乎是一个共同的需求?

谢谢

好的,这是一个复杂的,但它是可行的。 以下是我如何使用它。

在客户端,我使用了http://github.com/valums/file-uploader ,这是一个javascript库,允许多个文件上传,带有进度条和拖放支持。 它受到良好支持,高度可配置,基本实现很简单:

在视图中:

<div id='file-uploader'><noscript><p>Please Enable JavaScript to use the file uploader</p></noscript></div>

在js中:

var uploader = new qq.FileUploader({
   element: $('#file-uploader')[0],
   action: 'files/upload',
   onComplete: function(id, fileName, responseJSON){
     // callback
   }
});

当传递文件时,FileUploader将它们作为XHR请求发布到服务器,其中POST主体是原始文件数据,而头文件和文件名在URL字符串中传递(这是通过javascript异步上传文件的唯一方法)。

这是它变得复杂的地方,因为Paperclip不知道如何处理这些原始请求,你必须捕获它们并将它们转换回标准文件(最好是在它们点击你的Rails应用程序之前),这样Paperclip就能发挥它的魔力。 这是通过一些Rack Middleware完成的,它创建了一个新的Tempfile(记住:Heroku是只读的):

# Embarrassing note: This code was adapted from an example I found somewhere online
# if you recoginize any of it please let me know so I pass credit.
module Rack
  class RawFileStubber

    def initialize(app, path=/files\/upload/) # change for your route, careful.
      @app, @path = app, path
    end

    def call(env)
      if env["PATH_INFO"] =~ @path
        convert_and_pass_on(env)
      end
      @app.call(env)
    end

    def convert_and_pass_on(env)
      tempfile = env['rack.input'].to_tempfile      
      fake_file = {
        :filename => env['HTTP_X_FILE_NAME'],
        :type => content_type(env['HTTP_X_FILE_NAME']),
        :tempfile => tempfile
      }
      env['rack.request.form_input'] = env['rack.input']
      env['rack.request.form_hash'] ||= {}
      env['rack.request.query_hash'] ||= {}
      env['rack.request.form_hash']['file'] = fake_file
      env['rack.request.query_hash']['file'] = fake_file
      if query_params = env['HTTP_X_QUERY_PARAMS']
        require 'json'
        params = JSON.parse(query_params)
        env['rack.request.form_hash'].merge!(params)
        env['rack.request.query_hash'].merge!(params)
      end
    end

    def content_type(filename)
      case type = (filename.to_s.match(/\.(\w+)$/)[1] rescue "octet-stream").downcase
      when %r"jp(e|g|eg)"            then "image/jpeg"
      when %r"tiff?"                 then "image/tiff"
      when %r"png", "gif", "bmp"     then "image/#{type}"
      when "txt"                     then "text/plain"
      when %r"html?"                 then "text/html"
      when "js"                      then "application/js"
      when "csv", "xml", "css"       then "text/#{type}"
      else 'application/octet-stream'
      end
    end
  end
end

稍后,在application.rb中:

config.middleware.use 'Rack::RawFileStubber'

然后在控制器中:

  def upload
    @foo = modelWithPaperclip.create({ :img => params[:file] })
  end

这种方法可靠,但在同时上传大量文件时可能会很慢。

免责声明

这是针对具有单个,已知且受信任的后端用户的项目实现的。 它几乎肯定会对高流量Heroku应用程序产生一些严重的性能影响,并且我没有为安全性进行过防火测试。 那说,它绝对有效。

Ryan Bigg建议的方法是:

Daniel Mendel的file-uploader推荐非常棒。 这是一个非常棒的用户体验,比如Gmail拖放上传。 如果你对最新的中间件组件感兴趣,有人写了一篇关于如何使用rack-raw-upload中间件连接rails应用程序的博客文章。

还有一个最近更新的插件可能很有用

另一个(包括完整性。我没有调查过这个。)

这些问题高度相关

在Action的第8章中的Rails 3中介绍了这一点。但我没有介绍上传到S3或调整图像大小。

建议你单独购买它来解决这个问题可能听起来有点偏颇,但我可以保证你会回答你的其他问题。 它将行为驱动开发方法作为主要主题之一,在开发应用程序期间向您介绍Rails功能。 这不仅向您展示了如何构建应用程序,还使其可维护

至于上传后的图像大小调整,Paperclip有相当好的文档 如果您不理解任何选项/方法,我建议您阅读,然后在SO上提出另一个问题。

至于S3上传,你可以这样做:

has_attached_file :photo, :styles => { ... }, :storage => :s3

您需要使用S3详细信息配置Paperclip::Storage::S3以进行设置,Paperclip再次为此提供了一些非常棒的文档

祝好运!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM