2011-07-25 36 views
15

私は、サーバーにアップロードされたバイナリファイルを暗号化して保存する必要があるサイトを持っています。アップロードと保存が正常に動作しますが、暗号化されたファイルの書き込みしようとしたとき、私はこのエラーを取得しています:バイナリファイルを書き込む際のEncoding :: UndefinedConversionError

エンコーディング:: UndefinedConversionError(ASCII-8BITから "\ XDD" UTF-8へ):

をそれは次のように見える原因

コード:

fd_in = IO.sysopen(self[:name].tempfile.path, "rb")       
file_in = IO.open(fd_in)              
fd_out = IO.sysopen(self[:name].tempfile.path + ".encrypted", "wb")   
file_out = IO.open(fd_out)              
cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc')       
cipher.encrypt                           
cipher.key = cipher_key              
cipher.iv = cipher_iv              
while chunk = file_in.read(1024)            
    file_out << cipher.update(chunk)            
end 
file_out << cipher.final 

エラーがwhileループでfile_out < < cipher.update(チャンク)が生じライン。私はこれをオンラインで調べ、同様のASCII/UTF変換の問題のレポートを見つけましたが、すべてストリームファイル入力ではなく、強制的な文字列入力に基づいているようです。私は、デフォルトの文字列エンコーディングに影響すると思われるRuby 1.9.2を使用しています。

私はストリームベースのアプローチを使用する必要があります。ファイルは大きくなる傾向があり、処理するためにファイル全体(入力または出力)をメモリにロードしたくありません。

何か助けていただければ幸いです。ありがとう。

+0

私は使用しては.force_encoding(「UTF-8」)#updateと#finalの呼び出しでは、問題を解決することを発見しました。これが実際に正しい方法であるかどうか、誰かが(もし?)UTF-8が受け入れられれば、私は知りたいと思う。 –

+0

私はEncoding.default_externalとEncoding.default_internalもチェックしました。どちらもUTF-8です。 –

答えて

27

en/decryptingが入出力バイトを生のバイトとして扱う場合は、エンコードをすべてのコストでデータに関連付けることによるトランスコーディングを避けたいとします。ですから、バイナリモードでファイルを読み書き用に開く必要があります。

実際にはIO#sysopenを使用しましたが、IO#openを使用しているときに "b"フラグを渡しませんでした。あなたは、むしろこれをしようとした場合

あなたのコードは動作するはずです:

fin = File.open("TODO", "rb")       
fout = File.open("TODO.encrypted", "wb")   
cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc') 
cipher.encrypt      
cipher.key = key              
cipher.iv = iv              
while chunk = fin.read(1024)            
    fout << cipher.update(chunk)            
end 
fout << cipher.final 
fin.close 
fout.close 
+0

Ah - 私はIO#openが#sysopenのファイル記述子のモードを使用すると(間違って)仮定しました。ありがとう! –

関連する問題