2009-11-04 21 views
29

¿Cómo se maneja la carga de archivos en el riel sin adjuntarlos a un registro activo?
Solo quiero escribir los archivos en el disco.carga de archivos sin activerecord

Gracias,

+0

probar este http://easyrails.herokuapp.com/blogs/5/upload-file-in-rails-without-model- creación – vajapravin

Respuesta

54

Si he entendido bien lo que necesita a continuación, el ejemplo más simple sería la siguiente:

El controlador:

class UploadController < ApplicationController 
    def new 

    end 

    def create 
    name = params[:upload][:file].original_filename 
    path = File.join("public", "images", "upload", name) 
    File.open(path, "wb") { |f| f.write(params[:upload][:file].read) } 
    flash[:notice] = "File uploaded" 
    redirect_to "/upload/new" 
    end 
end 

La vista:

<% flash.each do |key, msg| %> 
    <%= content_tag :div, msg, :class => [key, " message"], :id => "notice_#{key}" %> 
<% end %> 
<% form_tag '/upload/create', { :multipart => true } do %> 
    <p> 
    <%= file_field_tag 'upload[file]' %> 
    </p> 
    <p> 
     <%= submit_tag "Upload" %> 
    </p> 
<% end %> 

Esto permitirá subir cualquier archivo sin ningún control o validación que en mi opinión no es tan útil.

Si lo hiciera yo mismo, entonces usaría algo como validatable gem o tableless gem simplemente sin pantalla ya no es compatible. Estas gemas te permitirán validar lo que estás cargando para hacerlo más sensato.

+1

Solo asegúrese de usar <% = form_tag ...%> en los rieles 3. – cider

+0

para ser coherente, ¿no debería usar 'File.join (" public "," images "," upload ")' para crear 'directory ¿? – Crashalot

+0

Claro, eso es un buen consejo. Escribí esto hace mucho tiempo :) No creo que supiera cómo hacerlo en ese momento :) Solo usé ejemplos al codificar, así que en una línea lo uso :)) Por otra parte, no. Actualizando ahora. –

0

Usted podría tratar de usar los carriles complemento Attachment_fu para manejar la carga de archivos. Le permite guardar las cargas en el sistema de archivos en lugar de la base de datos.

+0

attachement_fu necesita activerecord .... – Mike

3

La documentación Tempfile muestra un ejemplo que es equivalente al código de Rytis, que está bien la mayor parte del tiempo. Pero cuando llamas al tempfile.read, Ruby está leyendo todo el archivo como una sola porción en la memoria, que no es óptima.

Sin embargo, FileUtils proporciona un método copy_stream y IO, al menos en Ruby 2.0, proporciona una implementación copy_stream que se encarga de escribir directamente a una ruta de acceso (FileUtils.copy_stream requiere objetos de tipo fichero en ambos lados, o eso dicen los documentos).

En mi caso, estaba iniciando una gran carga de archivos múltiples a través de AJAX, y quería evitar leer todo el archivo (s) en la memoria de Ruby antes de escribir en el disco.

En el siguiente ejemplo, params[:files] es un Array de ActionDispatch::Http::UploadedFile casos, y local_filepath es una cadena que apunta a un archivo no existente en un directorio existente. Por razones de brevedad, voy a suponer que sólo estoy subiendo un archivo:

IO.copy_stream(params[:files][0].tempfile, local_filepath) 

La instancia ActionDispatch::Http::UploadedFile tiene un campo .tempfile que es sólo un ejemplo Tempfile regular.

No estoy seguro de que Ruby aún no esté leyendo todo el archivo en memoria, no comparé nada, pero es mucho más posible que con la sintaxis localfile.write(tempfile.read).

tl; dr: IO.copy_stream(your_tempfile, your_disk_filepath) es más conciso, si no más rápido.

4

simplemente puede mover el archivo temporal a la ruta de destino utilizando FileUtils

tmp = params[:my_file_field].tempfile 
destiny_file = File.join('public', 'uploads', params[:my_file_field].original_filename) 
FileUtils.move tmp.path, destiny_file 
Cuestiones relacionadas