Reputation: 624
I try to write AJAX uploaded image data:image/gif;base64,R0lGOD...
into file via IO. Got strange exception
in src/controllers/product.cr:41: instantiating 'Base64:Module#decode(IO+, File)'
Base64.decode(photo_b64_io, file)
in /usr/share/crystal/src/base64.cr:173: undefined method 'to_slice' for IO::ARGF (compile-time type is IO+)
from_base64(data.to_slice) do |byte|
My code
photo_b64_io = env.request.body.not_nil!
photo_b64_io.gets(",") # seek to real data
File.open(File.join(upload_path, file_path, file_id), "w") do |file|
Base64.decode(photo_b64_io, file)
end
How to improve?
Upvotes: 1
Views: 133
Reputation: 4857
Base64.decode
does not take an IO
as first parameter, it takes something that responds to to_slice
, so a String
or a Slice
usually.
You either have to read the entire IO into memory first before passing it to Base64.decode
, using IO#gets_to_end
(given it's base64 encoded data it should be safe to read into a String
).
Or if you want to stay memory-efficient you should read in chunks of an multiple of 4 (since with base64 encoding every 3 original bytes are encoded into 4 bytes), using IO#read
(ensure to loop until your chunk is full and handle the EOF case), and then decode each full chunk and write the result to a file before recycling your buffer for the next chunk.
Upvotes: 1