web-dev-qa-db-fra.com

Comment télécharger un fichier en Ruby sur rails?

Je suis très nouveau dans Ruby on Rails. Je suis coincé avec un problème. Je veux créer une fonctionnalité de téléchargement de fichier à travers laquelle je peux télécharger tout type de fichier (texte, image, etc.) Mon fichier de contrôleur est (upload_controller.rb):

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

Mon fichier modèle est (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

Mon fichier de vue est (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 %>

Maintenant, lorsque j'essaie de télécharger l'image, j'obtiens l'erreur "mode d'accès invalide wp" dans le fichier modèle. Lorsque je change File.open (chemin, "wp") en File.open (chemin, "w") dans le fichier modèle, cela donne l'erreur "'\ x89' de ASCII-8BIT à UTF-8". Pour le fichier .txt, cela fonctionne bien. J'utilise Ruby 1.9.3 et Rails 3.2.6

19
Vivacity InfoTech

Merci par exemple, j'étudie Rails aussi!

Il fonctionne en Rails 3.1

Mon code:

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

Manette

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

Voir 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 %>

Modèle

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
8
user1466717

Le problème est dû à des problèmes d'encodage. Il semble que vous lisez le fichier en mode ASCII-8BIT et que vous l'écrivez en UTF-8, ce qui signifie qu'une conversion doit avoir lieu. Et la conversion de ASCII-8BIT en UTF-8 n'est pas simple. Alternativement, vous pouvez spécifier le mode binaire pour la lecture et l'écriture des fichiers.

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

et

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

Une autre excellente option serait carrierwave , qui est très simple à installer et le guide sur github peut vous permettre d'être opérationnel en quelques minutes. Ajoutez-le à votre gemfile puis exécutez bundle install

Il y a aussi un bon railscast sur le sujet

2
Anconia

utilisez "wb" au lieu de "wp". Ça marche

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