Как написать Tempfile как бинарный файл - PullRequest
1 голос
/ 24 марта 2020

При попытке записать строковый / разархивированный файл в Tempfile , выполнив:

temp_file = Tempfile.new([name, extension])
temp_file.write(unzipped_io.read)

, который выдает следующую ошибку, когда я делаю это с изображением:

Encoding::UndefinedConversionError - "\xFF" from ASCII-8BIT to UTF-8

При исследовании я обнаружил, что это вызвано тем, что Ruby пытается записывать файлы с кодировкой по умолчанию (UTF-8). Но файл должен быть записан как двоичный файл, поэтому он игнорирует любое поведение файла, определяющее c поведение.

Запись обычного File вы можете сделать это следующим образом:

File.open('/tmp/test.jpg', 'rb') do |file| 
  file.write(unzipped_io.read)
end

Как это сделать в Tempfile

Ответы [ 3 ]

2 голосов
/ 24 марта 2020

Tempfile.new передает параметры в File.open, который принимает параметры из IO.new, в частности:

: binmode
Если значение является истинным значением, то же самое, что и «b» в аргументе mode.

Таким образом, чтобы открыть временный файл в двоичном режиме, вы должны использовать:

temp_file = Tempfile.new([name, extension], binmode: true)

temp_file.binmode?          #=> true
temp_file.external_encoding #=> #<Encoding:ASCII-8BIT>

Кроме того, вы можете использовать Tempfile.create, который принимает блок, автоматически закрывает и удаляет файл впоследствии:

Tempfile.create([name, extension], binmode: true) do |temp_file|
  temp_file.write(unzipped_io.read)
  # ...
end
1 голос
/ 24 марта 2020

Я встречал решение в старом Ruby сообщении на форуме, поэтому я подумал, что поделюсь им здесь, чтобы людям было легче найти:

https://www.ruby-forum.com/t/ruby-binary-temp-file/116791

Очевидно, Tempfile имеет недокументированный метод binmode, который меняет режим записи на двоичный и, таким образом, игнорирует любые проблемы с кодировкой:

temp_file = Tempfile.new([name, extension])
temp_file.binmode
temp_file.write(unzipped_io.read)

Спасибо неизвестно человек, который упомянул об этом на ruby -forums.com в 2007 году!

0 голосов
/ 24 марта 2020

Другая альтернатива - IO.binwrite(path, file_content)

...