2010-10-22 12 views
5

Tengo paper_clip instalado en mi aplicación Rails 3, y puedo cargar un archivo - ¡qué divertido y fácil!Rieles - Paper_Clip - Soporte para carga de múltiples archivos

El desafío ahora es permitir que un usuario cargue varios objetos. Ya sea haciendo clic en seleccionar fileS y poder seleccionar más de uno. O haga clic en un botón más y obtenga otro botón de carga de archivos.

No puedo encontrar ningún tutorial o gema para admitir esto de la caja. Impactante, sé ...

Cualquier sugerencia o solución. Parece una necesidad común?

Gracias

+0

Se olvidó de agregar. Estoy cargando imágenes que deben cambiar de tamaño.por eso no puedo cargar directamente a S3. Y estoy usando heroku para hosting. gracias – user479959

Respuesta

5

De acuerdo, este es complejo pero es factible. Así es como lo hice funcionar.

Del lado del cliente utilicé http://github.com/valums/file-uploader, una biblioteca de JavaScript que permite múltiples cargas de archivos con barra de progreso y soporte para arrastrar y soltar. Es bien apoyada, altamente configurable y la implementación básica es simple:

En la vista:

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

En el js:

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

Cuando los archivos zurdos, FileUploader las publicará en el servidor como una solicitud XHR donde el cuerpo POST es el archivo de datos sin formato mientras que los encabezados y el nombre del archivo se pasan en la cadena URL (esta es la única forma de cargar un archivo asincronously a través de javascript).

Aquí es donde se complica, ya que Paperclip no tiene idea de qué hacer con estas solicitudes crudas, tiene que capturarlas y convertirlas a archivos estándar (preferiblemente antes de que lleguen a la aplicación Rails), para que Paperclip pueda funcionar Es magia.Esto se hace con un poco de Rack middleware que crea un nuevo archivo temporal (recuerda: Heroku es de sólo lectura):

# 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 

Más tarde, en application.rb:

config.middleware.use 'Rack::RawFileStubber' 

Luego, en el controlador:

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

Esto funciona de manera confiable, aunque puede ser un proceso lento cuando se cargan muchos archivos simultáneamente.

Exención de responsabilidad

Esto se implementó para un proyecto con un único, conocido & usuario de confianza back-end. Es casi seguro que tiene algunas implicaciones graves de rendimiento para una aplicación Heroku de alto tráfico y no lo he probado para seguridad. Dicho eso, definitivamente funciona.

+0

wow gracias ... Pero si "crea un nuevo archivo temporal" no es compatible con Heroku? A menos que me esté perdiendo algo? – user479959

+0

OK resulta que heroku tiene un lugar para imágenes temporales. Otras preguntas. ¿A dónde va la clase RawFileStubber? – user479959

+0

Agregué el archivo raw_file_stubber.rb a/lib ... y luego agregué la configuración de configuración de application.rb que tiene arriba y traté de iniciar el servidor (rieles) pero recibí todo tipo de errores. P, ¿es amistoso el anterior Rails 3? – user479959

0

que cubren esto en el capítulo 8. Rails 3 in Action 's no cubro subir a S3 o cambiar el tamaño de imágenes sin embargo.

Recomendar que lo adquiera basándome únicamente en la solución de este problema puede sonar un poco parcial, pero puedo garantizarle que responderá a otras preguntas que tenga al final de la línea. Tiene un enfoque de Desarrollo impulsado por el comportamiento como uno de los temas principales, que le presenta las características de Rails durante el desarrollo de una aplicación. Esto le muestra no solo cómo puede construir una aplicación, sino también hacerlo que se puede mantener.

En cuanto al cambio de tamaño de las imágenes después de que se hayan cargado, Paperclip tiene pretty good documentation on that. Recomiendo leer y luego hacer otra pregunta sobre SO si no entiende ninguna de las opciones/métodos.

Y en cuanto a la carga S3, usted puede hacer esto:

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

que había necesidad de configurar Paperclip::Storage::S3 con sus datos S3 para su instalación, y de nuevo Paperclip tiene algunos pretty awesome documentation para esto.

¡Buena suerte!

4

El método Ryan Bigg recomienda está aquí:

El file-uploader recomendación por Daniel Mendel es realmente grande. Es una experiencia de usuario realmente increíble, como las cargas de arrastrar y soltar de Gmail. Alguien escribió una publicación en el blog sobre cómo conectarlo con una aplicación de rieles utilizando el middleware rack-raw-upload, si le interesa un componente de middleware actualizado.

También hay otro plugin que ha sido actualizado más recientemente que puede ser útil

Y otro (Incluido para la integridad. No he investigado éste.)

Estas preguntas están altamente relacionados

Cuestiones relacionadas