0

TL;DR

How would I specify the mode of encoding on File.write, or how would one save image binary to a file in a similar fashion?

More Details

I'm trying to download an image from a Trello card and then upload that image to S3 so it has an accessible URL. I have been able to download the image from Trello as binary (I believe it is some form of binary), but I have been having issues saving this as a .jpeg using File.write. Every time I attempt that, it gives me this error in my Rails console:

Encoding::UndefinedConversionError: "\xFF" from ASCII-8BIT to UTF-8
from /app/app/services/customer_order_status_notifier/card.rb:181:in `write'

And here is the code that triggers that:

def trello_pics
    @trello_pics ||=
    card.attachments.last(config_pics_number)&.map(&:url).map do |url|
      binary = Faraday.get(url, nil, {'Authorization' => "OAuth oauth_consumer_key=\"#{ENV['TRELLO_PUBLIC_KEY']}\", oauth_token=\"#{ENV['TRELLO_TOKEN']}\""}).body
      File.write(FILE_LOCATION, binary) # doesn't work
      run_me
    end
  end

So I figure this must be an issue with the way that File.write converts the input into a file. Is there a way to specify encoding?

McKay Whiting
  • 152
  • 11
  • Does this answer your question? [Write and read a file with utf-8 encoding](https://stackoverflow.com/questions/5163339/write-and-read-a-file-with-utf-8-encoding) – Int'l Man Of Coding Mystery Sep 14 '21 at 16:52
  • 3
    [`IO#binwrite`](https://ruby-doc.org/core-3.0.2/IO.html#method-c-binwrite) From the Docs: "Same as ::write except opening the file in binary mode and ASCII-8BIT encoding" – engineersmnky Sep 14 '21 at 16:59
  • 1
    Or `File.open(FILE_LOCATION, 'wb') do |file|; file.write(data); end`. https://ruby-doc.org/core-2.5.0/IO.html#method-c-new – max Sep 14 '21 at 17:02
  • @Int'lManOfCodingMystery I don't think so, but I could be wrong – McKay Whiting Sep 14 '21 at 18:36
  • @max or `File.write(FILE_LOCATION,data, mode: 'wb')` since `IO::write` takes the same mode arguments as `new` – engineersmnky Sep 15 '21 at 03:34
  • 1
    @engineersmnky if you open a file instance you can write as you stream the response. Otherwise go with the shorter variant. https://lostisland.github.io/faraday/usage/streaming – max Sep 15 '21 at 07:40

1 Answers1

3

AFIK you can't do it at the time of performing the write, but you can do it at the time of creating the File object; here an example of UTF8 encoding:

File.open(FILE_LOCATION, "w:UTF-8") do 
  |f|
  f.write(....)
end

Another possibility would be to use the external_encoding option:

File.open(FILE_LOCATION, "w", external_encoding: Encoding::UTF_8)

Of course this assumes that the data which is written, is a String. If you have (packed) binary data, you would use "wb" for openeing the file, and syswrite instead of write to write the data to the file.

UPDATE As engineersmnky points out in a comment, the arguments for the encoding can also be passed as parameter to the write method itself, for instance

IO::write(FILE_LOCATION, data_to_write, external_encoding: Encoding::UTF_8)
user1934428
  • 19,864
  • 7
  • 42
  • 87