2010-10-22 41 views
5

Ho paper_clip installato sulla mia app Rails 3 e posso caricare un file - wow è stato divertente e facile!Rails - Paper_Clip - Supporto per caricamenti di file multipli

La sfida ora è consentire a un utente di caricare più oggetti. Sia che si tratti di selezionare selezionare file e di poterne selezionare più di uno. O facendo clic su un altro pulsante e ottenendo un altro pulsante di caricamento file.

Non riesco a trovare tutorial o gemme per supportare questo fuori dalla scatola. Scioccante, lo so ...

Qualsiasi suggerimento o soluzione. Sembra un bisogno comune?

Grazie

+0

Hai dimenticato di aggiungere. Sto caricando immagini che devono essere ridimensionate.ecco perché non posso caricare direttamente su S3. E sto usando heroku per l'hosting. grazie – user479959

risposta

5

Ok, questo è complesso ma è fattibile. Ecco come ho potuto farlo funzionare.

Sul lato client ho utilizzato http://github.com/valums/file-uploader, una libreria javascript che consente più caricamenti di file con barra di avanzamento e supporto drag-and-drop. E 'ben supportato, altamente configurabile e l'implementazione di base è semplice:

Nella vista:

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

Negli js:

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

Quando i file handed, FileUploader loro messaggi al server come una richiesta XHR in cui il corpo POST è i dati del file raw mentre le intestazioni e il nome file vengono passati nella stringa URL (questo è l'unico modo per caricare un file in modo asincrono tramite javascript).

Ecco dove diventa complicato, poiché Paperclip non ha idea di cosa fare con queste richieste non elaborate, devi catturarle e convertirle di nuovo in file standard (preferibilmente prima che colpiscano la tua app Rails), in modo che Paperclip possa funzionare è magico.Questo viene fatto con un po 'di Middleware Rack che crea un nuovo File Temporanei (ricordate: Heroku è di sola lettura):

# 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 

Più tardi, nel application.rb:

config.middleware.use 'Rack::RawFileStubber' 

Poi nel controller:

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

Questo funziona in modo affidabile, anche se può essere un processo lento durante il caricamento di un sacco di file contemporaneamente.

NEGAZIONE

Questo è stato implementato per un progetto con un singolo, noto & attendibile dall'utente back-end. Quasi certamente ha delle serie implicazioni sulle prestazioni per un'app di Heroku ad alto traffico e non l'ho testato per sicurezza. Detto questo, funziona sicuramente.

+0

wow grazie ... Ma se "crea un nuovo Tempfile" non è compatibile con Heroku? A meno che mi manchi qualcosa? – user479959

+0

OK risulta che heroku ha un posto per le immagini temporanee. Altre domande. Dove va la classe RawFileStubber? – user479959

+0

Ho aggiunto il file raw_file_stubber.rb a/lib ... e poi ho aggiunto l'impostazione di configurazione application.rb che hai sopra e ho provato a lanciare il server (rails s) ma sono stato colpito da tutti i tipi di errori. Q, il suddetto Rails 3 è amichevole? – user479959

0

copro questo nel Capitolo Rails 3 in Action s' 8. Non coprire il caricamento su S3 o comunque ridimensionare le immagini.

Raccomandando di acquistarlo basandosi unicamente su di esso, questo problema potrebbe sembrare un po 'distorto, ma posso quasi garantirvi che risponderà ad altre domande che avete fatto. Ha un approccio allo sviluppo comportamentale come uno dei temi principali, introducendo le funzionalità di Rails durante lo sviluppo di un'applicazione. Questo mostra non solo come è possibile creare un'applicazione .

Per quanto riguarda il ridimensionamento delle immagini dopo che sono state caricate, Paperclip ha ottenuto pretty good documentation on that. Consiglierei di leggere e poi fare un'altra domanda su SO se non capisci nessuna delle opzioni/metodi.

E per quanto riguarda S3 upload, si può fare questo:

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

avresti bisogno di configurare Paperclip::Storage::S3 con i tuoi dati S3 per configurarlo, e di nuovo Paperclip avuto qualche pretty awesome documentation per questo.

Buona fortuna!

4

Il metodo Ryan Bigg raccomanda è qui:

Il file-uploader raccomandazione da Daniel Mendel è davvero grande. È un'esperienza utente davvero fantastica, come i caricamenti con trascinamento della selezione di Gmail. Qualcuno ha scritto un post sul blog su come collegarlo con un'applicazione per rails usando il middleware rack-raw-upload, se sei interessato a un componente middleware aggiornato.

C'è anche un altro plugin che è stato aggiornato di recente che può essere utile

E un altro (Incluso per completezza. Non ho studiato questo.)

Queste domande sono altamente correlati

Problemi correlati