2011-06-21 25 views
4

Ruby on Railsでアップロードされた画像のチェックサム(sha256)を生成しています。Rails:アップロードされたファイルのチェックサム

upload = params[:file] 
data1 = upload.read 
data2 = File.read(upload.tempfile) 
checksum1 = Digest::SHA256.hexdigest(data1) 
checksum2 = Digest::SHA256.hexdigest(data2) 
puts checksum1 
puts checksum2 

最後の2つの文が異なる値を返しています。 UploadedFileオブジェクトを使用してデータを読み取ることにより、checksum1が生成されます。 ファイルシステムから一時ファイルを読み取ることによってchecksum2が生成されます。

ActionDispatch :: Http :: UploadedFileのオブジェクトは、アップロードされたファイルの内容以上のものを返しますか?ファイルシステムに書き込まれたアップロードファイルのチェックサムを生成すると、checksum1(UploadedFile.read)ではなく、checksum2(一時ファイルチェックサム)と一致しています。

ファイルシステムから一時ファイルを読み込んで生成されたチェックサムは、オブジェクト(UploadedFile)の実装が変更される可能性があるため、より信頼性が高いと仮定しています。必要に応じて、ファイルシステム上の既存ファイルのチェックサムを生成する方が簡単です。

したがって、チェックサムの違いと信頼性の違いは何ですか?

ありがとうございます。


アップデート1: @あたりパブロ・castellazzi提案として、私はダイジェストを使用してハッシュを生成:: SHA256.file(upload.path).hexdigest。 @ Arsen7で述べたように、私は、ファイルを読むために、バイナリモードを使用すると、すべてのチェックサムが等しい:私たちはこのchecksum3はチェックサム1に等しいが、チェックサム2


からアップデート2の違い

このchecksum3を呼びましょう。

+3

今後参考になるように、ファイルチェックサムを取得するより良い方法は 'Digest :: SHA256.file(path_to_file).hexdigest'です。 File.readを使用すると、メモリ不足のエラーが発生する可能性があります。 –

答えて

2

'data1'と 'data2'の内容を比較しましたか?それらをファイルに保存して見てみてください。

最初に読み込む前にupload.rewindと呼ぶことをお勧めしますが、最初にファイルから読み込まれた生データを見てください。

更新:

あなたがWindows上であることを言いませんでした。この場合、ファイルを気にして、いわゆるバイナリモードで読む必要があります。

変更するには、このような何かにFile.read方法:

data2 = nil 
File.open(upload.path, "rb") {|f| data2 = f.read } 

.pathメソッドを使用してのパブロCastellazzi提案を実装)

私はあなたには、いくつかのバイナリセーフなエディタでファイルを開くことが示唆された(VIMたとえば、何が違うのかを比較してください。おそらく大部分のデータは同じであるかもしれませんが、いずれかのファイルの行末が異なっているか、あるいは別の違いがあるかもしれません。

Windowsの場合、最も一般的な問題はバイナリモードです。

+0

data1とdata2をディスクに書き込むと、data1が正しいイメージとして表示され、data2が歪んでしまいます。 – Srisa

+0

バイナリモードはありがとうございました。 :) Windows以外のマシンで 'rb'モードを使用できますか? – Srisa

+0

はい、できます。他のシステムでは、それは暗黙のうちに無視されます。そして私を「サー」と呼んではいけません。私はこのタイトルのためにあまりにも謙虚です;-)) – Arsen7

1

Rails 3.xデータを使用していると仮定すると、チェックサムは正しいです。DATA2の内容はと読むべきである:

data2 = File.read(upload.path) 

upload.tempfileは、ファイルオブジェクトではなく、一時ファイルへのパスを保持しているインスタンスです。

Hereが実装の詳細です。

File.read(File.read)は見つからないファイルまたは無効なファイル名について何らかの例外をスローする必要があるので、これは変です。

+0

一時ファイルへのパスが含まれています。以下はログからのデータです:[存在しない書式設定にはごめんなさい] パラメータ: "file" =>#>} – Srisa

+0

本当にありません。 @tempfileという表現からわかるように、 "C:/ DOCUME〜1/User1/LOCALS〜1/Temp/RackMultipart20110621-2496-1lnrcpi"を指すFileインスタンスです。パスは単なる文字列です。@ tempfile = "C:/ DOCUME〜1/User1/LOCALS〜1/Temp/RackMultipart20110621-2496-1lnrcpi" –

+0

そうです。私は 'パス'を使用しており、期待どおりに動作しています。おそらくFileオブジェクトのto_sメソッドがパスを返します... – Srisa

関連する問題