【问题标题】:Rails: checksum of uploaded filesRails:上传文件的校验和
【发布时间】:2011-06-21 10:45:21
【问题描述】:

我正在 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

这个校验和3等于校验和1,但不同于校验和2


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

【问题讨论】:

  • 为了将来参考,获取文件校验和的更好方法是Digest::SHA256.file(path_to_file).hexdigest。使用 File.read 可能会导致内存不足错误。

标签: ruby-on-rails windows file-upload checksum sha256


【解决方案1】:

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

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

更新:

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

File.read 方法更改为如下内容:

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

(实施 Pablo Castellazzi 建议使用.path 方法)

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

在 Windows 中,最常见的问题是二进制模式。

【讨论】:

  • 当我将data1和data2写入磁盘时,data1显示为正确的图像,data2被扭曲了。
  • 谢谢你,先生,它是二进制模式。 :) 我可以在非 Windows 机器上使用“rb”模式吗?
  • 是的,你可以。在其他系统上,它会被默默地忽略。不要叫我“先生”。我对这个标题太谦虚了;-))
  • 这也适用于我 - 一个跨平台的 ruby​​ 应用程序 - linux 和 windows。在我使用它之前,windows 是不同的
【解决方案2】:

假设您使用的是 Rails 3.x data1 校验和是正确的。 data2 内容应使用:

data2 = File.read(upload.path)

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

Here是相关的实现细节。

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

【讨论】:

  • tempfile 包含临时文件的路径。以下是日志中的数据:[抱歉不存在格式] 参数:“file”=>#<:http::uploadedfile:0x1c0c638 jpeg form-data name='\"file\";filename=\"lorry.jpg\"\r\nContent-Type:' image>>}
  • 并非如此。从表示中可以看出,@tempfile 是一个指向“C:/DOCUME~1/User1/LOCALS~1/Temp/RackMultipart20110621-2496-1lnrcpi”的文件实例。路径只是一个字符串,它的表示形式应该类似于 @tempfile="C:/DOCUME~1/User1/LOCALS~1/Temp/RackMultipart20110621-2496-1lnrcpi"
  • 你是对的。我使用了“路径”,它按预期工作。可能 File 对象上的 to_s 方法返回路径...
猜你喜欢
  • 1970-01-01
  • 2018-02-24
  • 1970-01-01
  • 2018-05-12
  • 1970-01-01
  • 2017-02-21
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
相关资源
最近更新 更多