2012-07-05 50 views
18

我在軌道上的紅寶石非常新。我遇到了一個問題。我想創建一個文件上傳功能,通過它我可以上傳任何類型的文件(文本,圖像等)。 我的控制文件(upload_controller.rb):如何在rails上用ruby上傳文件?

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 

我的模型文件(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 

我的視圖文件(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 %> 

現在,當我嘗試上傳圖片時,模型文件中出現錯誤「無效訪問模式wp」。當我在模型文件中將File.open(路徑,「wp」)更改爲File.open(path,「w」)時,會給出從ASCII-8BIT到UTF-8的錯誤「'\ x89'」。對於.txt文件,它工作正常。 我使用的是Ruby 1.9.3和Rails 3.2.6

+1

這個線程可能會有所幫助http://stackoverflow.com/questions/4988724/ruby-on-rails-upload-file-problem-odd-utf8-conversion-error [視頻上傳的 – 2012-07-05 11:17:27

+0

可能重複在Rails中的文件](http://stackoverflow.com/questions/14174044/uploading-a-file-in-rails) – Nateowami 2014-12-16 13:27:36

+1

routes.db文件是什麼樣子的?我正在爲自己嘗試。 – 2016-12-29 23:46:52

回答

3

問題的原因是編碼問題。看來您正在以ASCII-8BIT模式讀取文件並將其寫入UTF-8,這意味着需要進行轉換。並且從ASCII-8BIT到UTF-8的轉換不是直截了當的。或者,您可以爲讀取和寫入文件指定二進制模式。

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

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

我想說,看看[IO class](http://www.ruby-doc.org/core-1.9.3/IO.html#method-cnew),我覺得它給了更多的控制權。 – Kashyap 2012-07-05 11:35:07

+0

源代碼編碼[不影響](默認IO編碼)(http://blog.grayproductions.net/articles/ruby_19s_three_default_encodings/)。但我認爲用二進制數據做這件事不是個好主意。 – 2012-07-05 16:32:31

+0

我正在閱讀相同的鏈接:)發佈後發現它並無法完成閱讀。環境編碼有一些效果嗎? – Kashyap 2012-07-06 01:12:54

2

另一個偉大的選擇是carrierwave,這是安裝非常簡單,在GitHub上的指南可以讓你在幾分鐘的事上運行。它添加到您的Gemfile,然後運行bundle install

還有關於這個問題

8

謝謝例如一個良好的railscast,我研究軌道呢!

它可以在導軌3.1

我的代碼:

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

控制器

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 

查看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 %> 

型號

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

使用「wb」而不是「wp」。它的工作原理

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