Rails: контрольная сумма загруженных файлов - PullRequest
5 голосов
/ 21 июня 2011

Я генерирую контрольную сумму (sha256) загруженного изображения в Ruby on 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: в соответствии с предложением @ pablo-castellazzi я сгенерировал хэш с помощью Digest :: SHA256.file (upload.path) .hexdigest.Давайте назовем эту контрольную сумму3

Эта контрольная сумма3 равна контрольной сумме1, но отличается от контрольной суммы2


Обновление 2: если я использую двоичный режим для чтения файла, как упомянуто @ Arsen7, то всеконтрольные суммы равны.

Ответы [ 2 ]

2 голосов
/ 21 июня 2011

Сравнивали ли вы содержимое data1 и data2? Попробуйте сохранить их в файлы и посмотрите.

Полагаю, вы, возможно, захотите позвонить upload.rewind перед первым чтением, но прежде всего посмотрите на необработанные данные, прочитанные из файлов.

Обновление:

Вы не сказали, что находитесь на Windows. В этом случае вам следует позаботиться и прочитать файлы в так называемом двоичном режиме.

Измените метод File.read на что-то вроде этого:

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

(Реализация предложения Пабло Кастеллацци об использовании метода .path)

Я предлагал открыть файлы в каком-нибудь бинарно-безопасном редакторе (например, vim) и сравнить, что отличается. Вы могли бы заметить, что, возможно, большинство данных совпадают, но в одном из файлов окончания строк различны, или, возможно, вы заметите некоторые другие различия.

В случае Windows наиболее популярной проблемой является двоичный режим.

1 голос
/ 21 июня 2011

Если вы используете Rails 3.x, контрольная сумма data1 верна.содержимое data2 следует читать следующим образом:

data2 = File.read(upload.path)

upload.tempfile - это экземпляр, содержащий объект файла, а не путь к временному файлу.

Здесь - этосоответствующие детали реализации.

Также это странно, потому что File.read (File.read) должен выдавать какое-то исключение в отношении файла, который не найден, или неверного имени файла.

...