Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write a Tempfile as binary

When trying to write a string / unzipped file to a Tempfile by doing:

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

Which throws the following error when I do this with an image:

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

When researching it I found out that this is caused because Ruby tries to write files with an encoding by default (UTF-8). But the file should be written as binary, so it ignores any file specific behavior.

Writing regular File you would be able to do this as following:

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

How to do this in Tempfile

like image 831
Gijs Paulides Avatar asked Dec 14 '22 09:12

Gijs Paulides


2 Answers

Tempfile.new passes options to File.open which accepts the options from IO.new, in particular:

:binmode
If the value is truth value, same as “b” in argument mode.

So to open a tempfile in binary mode, you'd use:

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

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

In addition, you might want to use Tempfile.create which takes a block and automatically closes and removes the file afterwards:

Tempfile.create([name, extension], binmode: true) do |temp_file|
  temp_file.write(unzipped_io.read)
  # ...
end
like image 130
Stefan Avatar answered Dec 23 '22 13:12

Stefan


I have encountered the solution in an old Ruby forum post, so I thought I would share it here, making it easier for people to find:

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

Apparently Tempfile has an undocumented method binmode, which changes the writing mode to binary and thus ignoring any encoding issues:

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

Thanks unknown person who mentioned it on ruby-forums.com in 2007!

like image 20
Gijs Paulides Avatar answered Dec 23 '22 12:12

Gijs Paulides