Rails 파일 업로드 filefield 오류 Encoding::UndefinedConversionError

9727 단어 Railsfile_field
서버는 ubuntu12 64bit, 환경은 ruby1.9.3+rails3+mysql, 테스트는 윈도우즈 2003입니다.[.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
    Content-Type: application/octet-stream\r
    ", @
    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
    Content-Type: binary/octet-stream\r
    ", @
    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", 실패한 것은 @contenttype="binary/octet-stream". txt 파일을 업로드하려고 시도합니다. 성공했습니다. @contenttype 부분은 @contenttype="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 

한차례의 검색을 통해 심층적인 원인을 찾았는데 원래는 2진 파일이었기 때문에 루비는 2진 파일을 읽고 저장할 때 자동으로 처리하기 때문에 특별한 방식이 필요하지 않았다.
그러나 윈도우즈에서는 2진법과 텍스트 파일이 다르기 때문에 2진법 모드에서 끝줄은 하나의 단독 줄로 전환될 수 없고, 하나의 리턴과 하나의 줄로 저장된다.그래서 만약에 바이너리 파일을 읽는다면 오픈할 때 바이너리 파일을 읽는다는 것을 명시해야 한다.b는 2진법이라는 뜻이다.
그림은 기본적으로 2진 파일로 처리되어 있어서 당첨되었다.사실 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> 

안전한 측면에서 볼 때 파일 업로드는 경로, 권한, 업로드의 유형을 엄격하게 제어해야 한다. 
  • 경로는 바로 파일이 서버에 저장되는 경로이다. 가장 좋은 것은 단독 경로이다. 루트 디렉터리에 두지 말고 폴더를 계획하고 이름을 바꾸어야 한다. 업로드하는 사람이 서버에 같은 이름의 파일이 존재하는지 모르기 때문에 이것은 파일의 실제 이름과 사용자가 볼 수 있는 파일 이름의 비추기와 관련된다.

  •  
  • 권한은 사용자에게 경로를 업로드하는 권한입니다. 실행 권한은 없고 읽기와 쓰기 권한만 있으면 됩니다.필요하면 사용자 폴더를 구분해서 권한을 구분해야 합니다.공용 폴더를 보존합니다.등등, 상황에 따라 결정된다.

  •  
  • 업로드의 유형은 업로드 파일이 한 장면과 관련이 있을 것이다. 한 장면은 문서 장면, 이미지 장면 등 한 가지 파일만 필요할 수 있다.가장 좋은 것은 서로 다른 장면에서 서로 다른 파일 형식을 제어하는 것이다.집행 문서는 엄격하게 통제해야 한다.

  • 좋은 웹페이지 즐겨찾기