2013-03-10 6 views
8

Sto provando a creare un collegamento semplice che quando viene premuto avvia il download di un documento associato a una particolare risorsa. Ho un modello di risorsa e in quel modello c'è una colonna chiamata "documento". Sono in grado di visualizzare correttamente il documento in linea quando si fa clic sul collegamento, ma preferirei scaricarlo. Ho letto di content-types e send_file, ma non sono riuscito a ricostruirlo completamente per funzionare.Download di file dal collegamento del documento Carrierwave allegato

Ecco il codice che ho che ho bisogno di utilizzare per il link:
<%= link_to 'Download File', :action => "download_file" %>

Questo genera un errore:
ActiveRecord :: RecordNotFound in ResourcesController # mostrare Impossibile trovare risorse con id = download_file

Quando cambio il link a questo, si apre il file nel browser:
<%= link_to 'Open file', resource.document_url, :target => "_blank" %>

Nel mio ResourcesController ho questo metodo definito:

def download_file 
    @resource = Resource.find(params[:id]) 
    send_file(@resource.file.path, 
     :filename => @resource.file.name, 
     :type => @resource.file.content_type, 
     :disposition => 'attachment', 
     :url_based_filename => true) 
    end 

Ho un percorso allestito in routes.rb come questo:

resources :resources do 
    get 'resources', :on => :collection 
    end 

Quindi sulla base di questo errore, sembrerebbe che il mio metodo download_file in ResourcesController non è in grado di determinare l'ID del record di risorse a cui è associato il documento.

sto correndo: Rails 3.2.11 Carrierwave 0.8.0 di Ruby 1.9.3-P194

Gradirei qualche informazione in questo. Ho cercato un numero di articoli e non sono riuscito a trovare un semplice tutorial. Grazie.

+0

Grazie mille. Tutto questo ha funzionato a meraviglia. Rails 4 - CarrierWave. –

risposta

13

Sono stato in grado di capirlo. Cercherò di spiegare come ho risolto questo problema.

Il metodo download_file era posizionato correttamente in ResourcesController, ma non stavo usando i nomi delle variabili corrette. Ecco la definizione metodo corretto per i miei scopi:

def download_file 
    @resource = Resource.find(params[:id]) 
    send_file(@resource.document.path, 
     :type => 'application/pdf', 
     :disposition => 'attachment', 
     :url_based_filename => true) 
    end 

Nel mio caso ho un record restituito nella @Resource variabile che ha un documento ad esso associati (di nuovo, sto usando Carrierwave). Quindi il primo argomento richiesto da send_file è il percorso (vedere API for send_file). Questa informazione sul percorso è fornita da @ resource.document.path.

send_file accetta un numero di altri argomenti, che sembrano essere facoltativi perché ne avevo solo bisogno tre. Vedi la documentazione dell'API per gli altri argomenti.

Uno di quelli che ha generato l'errore per me era il tipo :. Gli stavo passando la variabile "@ resource.file.content_type", ma apparentemente cercava un valore letterale. Una volta passato l'application/pdf, ha funzionato. Senza impostare esplicitamente questo, il file che viene scaricato non ha aggiunto l'estensione del file. In ogni caso, per la mia app questo documento potrebbe essere una varietà di diversi mime-tipi da pdf a word a mp4. Quindi non sono sicuro di come specificare più.

L'argomento veramente importante per i miei scopi (scaricare anziché visualizzare nel browser) è la: disposizione che deve essere impostata su "allegato" anziché "in linea".

L'altro argomento: url_based_filename è apparentemente utilizzato per determinare il nome del file dall'URL. Dal momento che non sto fornendo il nome del file, forse questo è l'unico modo per me di fornire quello al file che viene scaricato, ma non ne sono sicuro.

ho anche bisogno di cambiare il tag link_to a questo:
<%= link_to 'Download File', :action => 'download_file', :id => resource.id %>

Nota che alimentare il: simbolo id con l'id della risorsa corrente fornito le informazioni specifiche necessarie per identificare la risorsa in questione.

Spero che questo aiuti qualcun altro. Questo deve essere molto ovvio per tutti gli altri, perché non ho trovato alcun tutorial di base sul download dei file. Sto ancora imparando molto.

AGGIORNAMENTO: Ho dovuto giocare con questo per ottenere il comportamento desiderato. Ecco il nuovo metodo che funziona:

 def download_file 
     @resource = Resource.find(params[:id]) 
     send_file(@resource.document.path, 
       :disposition => 'attachment', 
       :url_based_filename => false) 
     end 

Con queste modifiche non devo più impostare: tipo. L'impostazione ": url_based_filename => true" continuava a denominare il file dopo l'ID del record nell'URL. L'impostazione di questo valore su false sembra controintuitiva in base alla mia lettura della funzione di questo argomento, tuttavia, ottenendo i risultati desiderati di denominare il file dopo il nome del file effettivo.

ho anche usato il mime-types gem e aggiungere il seguente al mio file video_uploader.rb:

require 'carrierwave/processing/mime_types' 

class VideoUploader < CarrierWave::Uploader::Base 
include CarrierWave::MimeTypes 
process :set_content_type 

Questo gioiello imposta a quanto pare il mime-type intuito dal l'estensione del file nel nome del file. In questo modo non è stato necessario per me impostare: digita esplicitamente negli argomenti send_file nel mio metodo download_file.

+0

Grazie per queste informazioni! – tkrajcar

+0

Uso la gemma Carrierwave e quando scarico il file, se il nome del file contiene spazio, viene convertito in caratteri di sottolineatura. Quindi, come rimuovere quel carattere di sottolineatura dal nome del file durante il download? –