5

我正在 Ruby on Rails 中生成上传图像的校验和 (sha256)。

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

最后两个语句返回不同的值。checksum1 是通过使用 UploadedFile 对象读取数据生成的。checksum2 是通过从文件系统中读取临时文件生成的。

ActionDispatch::Http::UploadedFile 的对象是否返回上传文件的内容以外的任何内容?当我生成写入文件系统的上传文件的校验和时,它与checksum2(temporary file checksum) 匹配,而不是与checksum1(UploadedFile.read) 匹配。

我假设通过从文件系统读取临时文件生成的校验和更可靠,因为对象(UploadedFile)实现可能会发生变化。如果需要,生成文件系统上现有文件的校验和会更容易。

那么,校验和不同的原因是什么,哪个更可靠呢?

谢谢你。


更新 1:根据@pablo-castellazzi 的建议,我使用 Digest::SHA256.file(upload.path).hexdigest 生成了哈希。让我们称之为校验和3

这个 checksum3 等于 checksum1 但不同于 checksum2


更新2:如果我使用二进制模式读取@Arsen7 提到的文件,那么所有校验和都是相等的。

4

2 回答 2

2

您是否比较了“data1”和“data2”的内容?尝试将它们保存到文件并查看。

我想,您可能想upload.rewind在第一次读取之前调用,但首先是查看从文件中读取的原始数据。

更新:

你没有说你在 Windows 上。在这种情况下,您应该小心并以所谓的“二进制”模式读取文件。

将方法更改为File.read如下所示:

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

(执行 Pablo Castellazzi 的使用.path方法建议)

我建议您在一些二进制安全编辑器(例如 vim)中打开文件并比较不同之处。您会注意到,也许大多数数据是相同的,但其中一个文件的行尾不同,或者您可能会发现其他一些差异。

对于 Windows,最常见的问题是二进制模式。

于 2011-06-21T11:29:27.227 回答
1

假设您使用的是 Rails 3.x data1 校验和是正确的。data2 内容应通过以下方式读取:

data2 = File.read(upload.path)

upload.tempfile 是保存文件对象的实例,而不是临时文件的路径。

以下是相关的实现细节。

这也很奇怪,因为 File.read(File.read) 应该抛出某种关于找不到文件或无效文件名的异常。

于 2011-06-21T11:43:52.623 回答