2012-07-05 36 views
18

Soy muy nuevo en ruby ​​on rails. Estoy atascado con un problema. Quiero hacer una funcionalidad de carga de archivos a través de la cual pueda cargar cualquier tipo de archivo (texto, imagen, etc.). Mi archivo de controlador es (upload_controller.rb):¿Cómo subir un archivo en ruby ​​on rails?

class UploadController < ApplicationController 
def index 
    render :file => 'app\views\upload\uploadfile.html.erb' 
end 
def uploadFile 
    post = DataFile.save(params[:upload]) 
    render :text => "File has been uploaded successfully" 
end 
end 

Mi archivo de modelo es (data_file.rb):

class DataFile < ActiveRecord::Base 
    attr_accessor :upload 
    def self.save(upload) 
    name = upload['datafile'].original_filename 
    directory = 'public/data' 
    # create the file path 
    path = File.join(directory,name) 
    # write the file 
    File.open(path, "wp") { |f| f.write(upload['datafile'].read)} 
    end 
end 

Mi archivo de Vista es (uploadfile.html.erb):

<h1>File Upload</h1> 
<%= form_tag({:action => 'uploadFile'}, :multipart => true) do %> 
<p><label for="upload_file">Select File</label> 
<%= file_field 'upload', 'datafile' %></p> 
<%= submit_tag "Upload" %> 
<% end %> 

Ahora, cuando intento cargar la imagen, aparece el error "modo de acceso no válido wp" en el archivo del modelo. Cuando cambio File.open (ruta, "wp") a File.open (ruta, "w") en el archivo de modelo, aparece el error "'\ x89' de ASCII-8BIT a UTF-8". Para el archivo .txt, funciona bien. Estoy usando ruby ​​1.9.3 y rieles 3.2.6

+1

este hilo podría ser útil http://stackoverflow.com/questions/4988724/ruby-on-rails-upload-file-problem-odd-utf8-conversion-error –

+0

posible duplicado de [Carga un archivo en Rails] (http://stackoverflow.com/questions/14174044/uploading-a-file-in-rails) – Nateowami

+1

¿cómo se ve el archivo routes.db para esto? Lo estoy intentando por mí mismo. –

Respuesta

3

El motivo del problema son los problemas de codificación. Parece que está leyendo el archivo en modo ASCII-8BIT y escribiéndolo en UTF-8, lo que significa que debe llevarse a cabo una conversión. Y la conversión de ASCII-8BIT a UTF-8 no es sencilla. Alternativamente, puede especificar el modo binario para leer y escribir los archivos.

upload_file = File.new(<original file>, "rb").read 

y

File.open(<final uploaded file>, "wb") {|f| f.write(upload_file) } 
+0

Diría, eche un vistazo a la [clase IO] (http://www.ruby-doc.org/core-1.9.3/IO.html#method-c-new) que creo que da más control . – Kashyap

+0

Codificación de código fuente [no afecta] (http://blog.grayproductions.net/articles/ruby_19s_three_default_encodings/) la codificación IO predeterminada.Sin embargo, no creo que sea una buena idea hacer esto con datos binarios. –

+0

Estaba leyendo el mismo enlace :) Lo encontré después de publicar esto y no pude completar su lectura. La codificación del entorno tiene algún efecto, ¿no? – Kashyap

2

Otra gran opción sería carrierwave, que es muy sencillo de instalar y la guía en github que puede tener en marcha y funcionando en cuestión de minutos. Añadirlo a su Gemfile continuación, ejecute bundle install

También hay una buena railscast sobre el tema

8

Gracias por ejemplo, estudio rieles también!

Funciona de carriles 3.1

Mi código:

Routes 
resources :images do 
     collection { post :upload_image } 
    end 

controlador

class ImagesController < ApplicationController 
    def index 
    @car = Car.find(params[:car_id]) 
    @images = @car.images.order("order_id") 
    end 

    def upload_image 
    DataFile.save_file(params[:upload]) 
    redirect_to images_path(:car_id => params[:car_id]) 
    end 

Ver index.html.erb

<h1>File Upload</h1> 
    <%= form_tag({:action => 'upload_image', :car_id => @car.id}, :multipart => true) do %> 
    <p><label for="upload_file">Select File</label> 
    <%= file_field 'upload', 'datafile' %></p> 
    <%= submit_tag "Upload" %> 
    <% end %> 

    <% @images.each do |image| %> 
    <%= image.id %><br/> 
    <%= image.name %> 
    <% end %> 

Modelo

class DataFile < ActiveRecord::Base 
    attr_accessor :upload 

    def self.save_file(upload) 

    file_name = upload['datafile'].original_filename if (upload['datafile'] !='')  
    file = upload['datafile'].read  

    file_type = file_name.split('.').last 
    new_name_file = Time.now.to_i 
    name_folder = new_name_file 
    new_file_name_with_type = "#{new_name_file}." + file_type 

    image_root = "#{RAILS_CAR_IMAGES}" 


    Dir.mkdir(image_root + "#{name_folder}"); 
     File.open(image_root + "#{name_folder}/" + new_file_name_with_type, "wb") do |f| 
     f.write(file) 
     end 

    end 
end 
2

utilice "wb" en lugar de "wp". funciona

File.open(path, "wb") { |f| f.write(upload['datafile'].read)}