程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Rails文件上傳file_field報錯Encoding::UndefinedConversionError

Rails文件上傳file_field報錯Encoding::UndefinedConversionError

編輯:關於JAVA

服務器用的是ubuntu12 64bit,環境是ruby1.9.3+rails3+mysql,測試是在windows2003上。

上傳 一個【.gitconfig】文件,沒有問題,上傳【新浪微博數據挖掘.pdf】報錯,上傳【back.jpg】報錯。

下 面是兩段信息,是從【log/production.log】中粘貼出來的。上面一段你是沒有問題的日志,下面一段是報錯 之後的日志。

01.Started POST "/posts" for 106.3.102.43 at 2012-10-29 21:16:26 +0800
02.Processing by PostsController#create as HTML
03. Parameters: {"utf8"=>"?", "authenticity_token"=>"QG8aU6/VW5ZMagzyGhjdbm7fSzr4MB5CKdJeGBIeOa4=", "post"=>{"category_id"=>"1", "title"=>"666666666666", "url"=>"6666666", "picture"=>#<ActionDispatch::Http::UploadedFile:0x000000032fb838 @original_filename=".gitconfig", @content_type="application/octet-stream", @headers="Content-Disposition: form-data; name=\"post[picture]\"; filename=\".gitconfig\"\r\nContent-Type: application/octet-stream\r\n", @tempfile=#<File:/tmp/RackMultipart20121029-2609-1lrmc9o>>, "content"=>"6666", "tags_attributes"=>{"0"=> {"title"=>""}}}, "commit"=>"Create Post"}
04.Redirected to http://42.121.5.68/posts
05.Completed 302 Found in 36ms (ActiveRecord: 30.1ms)
01.Started POST "/posts" for 123.114.36.100 at 2012-10-30 08:58:13 +0800
02.Processing by PostsController#create as HTML
03. Parameters: {"utf8"=>"?", "authenticity_token"=>"rRnhcDWYDn+OntxxC2LmIEHpSpjWI5glrs6JlprG1Ho=", "post"=>{"category_id"=>"1", "title"=>"博 客嘗試最新法寶", "url"=>"post7", "picture"=>#<ActionDispatch::Http::UploadedFile:0x000000030df9a0 @original_filename="新浪微博數據挖掘方案.pdf", @content_type="binary/octet- stream", @headers="Content-Disposition: form-data; name=\"post[picture]\"; filename=\"\xE6\x96\xB0\xE6\xB5\xAA\xE5\xBE\xAE\xE5\x8D\x9A\xE6\x95\xB0\xE6\x8D\xAE\xE6 \x8C\x96\xE6\x8E\x98\xE6\x96\xB9\xE6\xA1\x88.pdf\"\r\nContent-Type: binary/octet- stream\r\n", @tempfile=#<File:/tmp/RackMultipart20121030-16129-15agvlb>>, "content"=>"博客嘗>試最新法寶", "tags_attributes"=> {"0"=>{"title"=>"博客嘗試最新法寶"}}}, "commit"=>"Create Post"}
04.Completed 500 Internal Server Error in 45ms
05.
06.Encoding::UndefinedConversionError ("\xE2" from ASCII-8BIT to UTF-8):
07. app/controllers/posts_controller.rb:60:in `write'
08. app/controllers/posts_controller.rb:60:in `block (2 levels) in create'
09. app/controllers/posts_controller.rb:59:in `open'
10. app/controllers/posts_controller.rb:59:in `block in create'
11. app/controllers/posts_controller.rb:56:in `create'

比較之後,發現兩段的picture部分的@content_type不一樣,成功的是 @content_type="application/octet-stream",失敗的是@content_type="binary/octet- stream"。

嘗試上傳一個txt文件,成功了,@content_type部分是 @content_type="text/plain"。

確定是這個部分的原因,也就是編碼,所以報錯編碼錯誤,未 定義編碼轉換。

上傳部分的代碼如下

uploaded_io = params[:post][:picture] 
        if uploaded_io != nil and uploaded_io.content_type.match('image') 
     
          File.open(Rails.root.join('public','uploads',uploaded_io.original_filename),'w') do 

|f| 
     
            f.write(uploaded_io.read) 
          end 
     
        else
end

經過一番查找,找到了深層的原因,原來是二進制文件的緣故,ruby在讀取和保存的時候會自動 處理二進制文件,不需要特殊的方式。

可是在windows中,二進制和文本文件是不同的,在二進制mode 下,結束行不能被轉義為一個單獨的換行,而是被保存為一個回車和一個換行。所以如果讀取的是二進制文件 ,需要在open的時候要指明讀取的是二進制文件wb。b就是二進制的意思。

圖片默認按照二進制文件處 理,所以就中招了。其實也只需要把w改成wb就可以了。

下面就沒有這個問題了。

uploaded_io = params[:post][:picture] 
        if uploaded_io != nil and uploaded_io.content_type.match('image') 
     
          File.open(Rails.root.join('public','uploads',uploaded_io.original_filename),'wb') do 

|f| 
     
            f.write(uploaded_io.read) 
          end 
     
        else
end
<div class="field"> 
  <%= f.label :picture %><br/> 
  <%= f.file_field :picture %> 
</div>

從安全角度來講,文件上傳要嚴格控制路徑,權限,以及上傳的類型。

   路徑,就是文件在服務器的保存路徑,最好是單獨路徑,不要放在根目錄,規劃好文件夾,還 要做好重命名,因為上傳的人不知道服務器上面是不是存在同名的文件,這就涉及文件實際的名稱和用戶需要 看到的文件名的映射。

   權限,就是上傳路徑給用戶的權限,最好不要有執行權限,只 有讀寫權限就可以了。有必要的話,需要劃分用戶文件夾來區分權限。保留一個公共文件夾。等等,根據情況 而定。

   上傳的類型,上傳文件肯定和一個場景相關,一個場景可能只需要一類文件, 比如文檔場景,圖片場景。最好在不同的場景控制不同的文件類型。執行文件要嚴格控制。

出處http://virusswb.blog.51cto.com/115214/1042740

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved