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

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


上傳一個【.gitconfig】文件,沒有問題,上傳【新浪微博數據挖掘.pdf】報錯,上傳【back.jpg】報錯。
下面是兩段信息,是從【log/production.log】中粘貼出來的。上面一段你是沒有問題的日志,下面一段是報錯之后的日志。

?

 
  1. Started?POST?"/posts"?for?106.3.102.43?at?2012-10-29?21:16:26?+0800?
  2. Processing?by?PostsController#create?as?HTML?
  3. ??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"}?
  4. Redirected?to?http://42.121.5.68/posts?
  5. Completed?302?Found?in?36ms?(ActiveRecord:?30.1ms)?




?

 
  1. Started?POST?"/posts"?for?123.114.36.100?at?2012-10-30?08:58:13?+0800?
  2. Processing?by?PostsController#create?as?HTML?
  3. ??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"}?
  4. Completed?500?Internal?Server?Error?in?45ms?
  5. ?
  6. Encoding::UndefinedConversionError?("\xE2"?from?ASCII-8BIT?to?UTF-8):?
  7. ??app/controllers/posts_controller.rb:60:in?`write'?
  8. ??app/controllers/posts_controller.rb:60:in?`block?(2?levels)?in?create'?
  9. ??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"。

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

上傳部分的代碼如下

?

 
  1. uploaded_io?=?params[:post][:picture]?
  2. ????????if?uploaded_io?!=?nil?and?uploaded_io.content_type.match('image')?
  3. ?
  4. ??????????File.open(Rails.root.join('public','uploads',uploaded_io.original_filename),'w')?do?|f|?
  5. ?
  6. ????????????f.write(uploaded_io.read)?
  7. ??????????end?
  8. ?
  9. ????????else?
  10. end?

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

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

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

?

下面就沒有這個問題了。

 
  1. uploaded_io?=?params[:post][:picture]?
  2. ????????if?uploaded_io?!=?nil?and?uploaded_io.content_type.match('image')?
  3. ?
  4. ??????????File.open(Rails.root.join('public','uploads',uploaded_io.original_filename),'wb')?do?|f|?
  5. ?
  6. ????????????f.write(uploaded_io.read)?
  7. ??????????end?
  8. ?
  9. ????????else?
  10. end

?

?

 
  1. <div?class="field">?
  2. ??<%=?f.label?:picture?%><br/>?
  3. ??<%=?f.file_field?:picture?%>?
  4. </div>?



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

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

?

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

?

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


?




本文轉自 virusswb 51CTO博客,原文鏈接:http://blog.51cto.com/virusswb/1042740,如需轉載請自行聯系原作者

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/392204.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/392204.shtml
英文地址,請注明出處:http://en.pswp.cn/news/392204.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

好久不來這里寫東西了.

我正準備離開學校去實現自己的目標,很清楚自己在學校的... ...做共享程序員,就不得不考慮些商業上的東西,自己要吃飯啊!我想我是該好好的處理一下這二者的關系. 轉載于:https://www.cnblogs.com/wangxiang/archive/2007/01/01/609714.html

Asp.net mvc中使用配置Unity

第一步&#xff1a;添加unity.mvc 第二步&#xff1a;在添加之后會在app_start中生成UnityConfig.cs&#xff0c;UnityMvcActivator.cs 第三步&#xff1a;使用 第四步&#xff1a;效果展示 轉載于:https://www.cnblogs.com/WJ--NET/p/7117839.html

頂級數據恢復_頂級R數據科學圖書館

頂級數據恢復Data science is the discipline of making data useful數據科學是使數據有用的學科 When we talk about the top programming language for Data Science, we often find Python to be the best fit for the topic. Sure, Python is undoubtedly an excellent cho…

xp系統oracle數據庫,Oracle10g 數據庫的安裝基于windowsXP

Oracle的安裝一、首先去官網下載自身系統相對應的數據庫軟件http://www.oracle.com/cn/index.htmlOracle軟件本身是免費的&#xff0c;個人用途完全沒關系&#xff0c;商業用途并被發現才會被Oracle所要求收費&#xff0c;收費買的不是軟件&#xff0c;而是授權。何謂授權&…

了解React Native中的不同JavaScript環境

by Khoa Pham通過Khoa Pham 了解React Native中的不同JavaScript環境 (Get to know different JavaScript environments in React Native) React Native can be very easy to get started with, and then at some point problems occur and we need to dive deep into it.Reac…

分布與并行計算—生命游戲(Java)

生命游戲其實是一個零玩家游戲&#xff0c;它包括一個二維矩形世界&#xff0c;這個世界中的每個方格居住著一個活著的或死了的細胞。一個細胞在下一個時刻生死取決于相鄰八個方格中活著的或死了的細胞的數量。如果相鄰方格活著的細胞數量過多&#xff0c;這個細胞會因為資源匱…

正確認識 Vista 激活期限

當我們在安裝 Vista 時&#xff0c;可以不輸入序列號進行安裝&#xff0c;這和以往的操作系統安裝有所不同&#xff0c;我們不必再為安裝系統時找不到我們的序列號標簽而發愁。如果不輸入序列號而繼續安裝系統&#xff0c;那么系統將提示我們有30天的激活期限&#xff01;這里的…

Oracle使用hs odbc連接mssql2008

1.創建odbc 2.在 product\11.2.0\dbhome_1\hs\admin\ 下拷貝initdg4odbc,把名字改為initcrmsql&#xff08;init所建odbc的名稱&#xff09; HS_FDS_CONNECT_INFO crmsql #odbc名稱 HS_FDS_TRACE_LEVEL 0 HS_FDS_RECOVERY_ACCOUNTsa #要連接的數據庫名稱 HS_FDS_RECOVERY_PWD…

oracle修改物化視圖字段,獲取物化視圖字段的修改矢量(一)

當表建立了物化視圖日志之后&#xff0c;表的DML修改會被記錄到物化視圖日志中&#xff0c;而物化視圖日志則包含了一個修改矢量&#xff0c;來記錄哪個列被修改。在文章列的修改矢量可以通過2的N次方來獲得&#xff0c;也就是POWER(2, N)。而N的值&#xff0c;就是列的位置。但…

聚合 數據處理_R中聚合的簡介:強大的數據處理工具

聚合 數據處理by Satyam Singh Chauhan薩蒂揚辛格喬漢(Satyam Singh Chauhan) R中聚合的簡介&#xff1a;強大的數據處理工具 (An introduction to aggregates in R: a powerful tool for playing with data) Data Visualization is not just about colors and graphs. It’s …

大數據 notebook_Dockerless Notebook:數據科學期待已久的未來

大數據 notebookData science is hard. Data scientists spend hours figuring out how to install that Python package on their laptops. Data scientists read many pages of Google search results to connect to that database. Data scientists write a detailed docume…

【NGN學習筆記】6 代理(Proxy)和背靠背用戶代理(B2BUA)

1. 什么是Proxy模式&#xff1f; 按照RFC3261中的定義&#xff0c;Proxy服務器是一個中間的實體&#xff0c;它本身即作為客戶端也作為服務端&#xff0c;為其他客戶端提供請求的轉發服務。一個Proxy服務器首先提供的是路由服務&#xff0c;也就是說保證請求被發到更加”靠近”…

分布與并行計算—并行計算π(Java)

并行計算π public class pithread extends Thread {private static long mini1000000000;private long start,diff;double sum0;double cur1/(double)mini;public pithread(long start,long diff) {this.startstart;this.diffdiff;}Overridepublic void run() {long istart;f…

linux復制文件跳過相同,Linux cp指令,怎么跳過相同的文件

1、使用cp命令的-n參數即可跳過相同的文件 。2、cp命令使用詳解&#xff1a;1)、用法&#xff1a;cp [選項]... [-T] 源文件 目標文件或&#xff1a;cp [選項]... 源文件... 目錄或&#xff1a;cp [選項]... -t 目錄 源文件...將源文件復制至目標文件&#xff0c;或將多個源文件…

eclipse類自動生成注釋

1.創建新類時自動生成注釋 window&#xff0d;>preference&#xff0d;>java&#xff0d;>code styple&#xff0d;>code template 當你選擇到這部的時候就會看見右側有一個框顯示出code這個選項&#xff0c;你點開這個選項&#xff0c;點一下他下面的New …

rman恢復

--建表create table sales( product_id number(10), sales_date date, sales_cost number(10,2), status varchar2(20));--插數據insert into sales values (1,sysdate-90,18.23,inactive);commit; --啟用rman做全庫備份 運行D:\autobackup\rman\backup_orcl.bat 生成…

微軟大數據_我對Microsoft的數據科學采訪

微軟大數據Microsoft was one of the software companies that come to hire interns at my university for 2021 summers. This year, it was the first time that Microsoft offered any Data Science Internship for pre-final year undergraduate students.微軟是到2021年夏…

再次檢查打印機名稱 并確保_我們的公司名稱糟透了。 這是確保您沒有的方法。...

再次檢查打印機名稱 并確保by Dawid Cedrych通過戴維德塞德里奇 我們的公司名稱糟透了。 這是確保您沒有的方法。 (Our company name sucked. Here’s how to make sure yours doesn’t.) It is harder than one might think to find a good business name. Paul Graham of Y …

linux中文本查找命令,Linux常用的文本查找命令 find

一、常用的文本查找命令grep、egrep命令grep&#xff1a;文本搜索工具&#xff0c;根據用戶指定的文本模式對目標文件進行逐行搜索&#xff0c;先是能夠被模式匹配到的行。后面跟正則表達式&#xff0c;讓grep工具相當強大。-E之后還支持擴展的正則表達式。# grep [options] …

分布與并行計算—日志挖掘(Java)

日志挖掘——處理數據、計費統計 1、讀取附件中日志的內容&#xff0c;找出自己學號停車場中對應的進出車次數&#xff08;in/out配對的記錄數&#xff0c;1條in、1條out&#xff0c;視為一個車次&#xff0c;本日志中in/out為一一對應&#xff0c;不存在缺失某條進或出記錄&a…