2011-06-21 67 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 

最后两条语句返回不同的值。 校验和1是通过使用UploadedFile对象读取数据而生成的。 校验和2是通过从文件系统读取临时文件生成的。

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

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

那么,校验和与哪一个更可靠的区别是什么原因呢?

谢谢。


更新1: 作为每@巴勃罗-卡斯特建议我通过使用摘要:: SHA256.file(upload.path).hexdigest生成的散列。让我们把这个checksum3

这checksum3等于校验码,但是从校验码


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

+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 } 

(用C语言实现.path方法的巴勃罗·卡斯特建议)

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

在Windows的情况下,最流行的问题是二进制模式。

+0

当我将data1和data2写入磁盘时,data1显示为适当的图像,data2变形。 – Srisa

+0

谢谢先生,它是二进制模式。 :) 我可以在非Windows机器上使用'rb'模式吗? – Srisa

+0

是的,你可以。在其他系统上,它被默默忽略。别叫我“先生”。我对这个标题太谦虚了;-)) – Arsen7

1

假设您正在使用Rails 3.x data1校验和是正确的。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-1lrcrc”的File实例。路径只是一个字符串,它的表示应该像@ tempfile =“C:/ DOCUME〜1/User1/LOCALS〜1/Temp/RackMultipart20110621-2496-1lnrcpi” –

+0

你是对的。我已经使用'路径',它按预期工作。 File对象上的to_s方法可能返回路径... – Srisa