Open and save base64 encoded image data URI in Ruby

From several posts I've seen, I am trying this

x = Base64.decode64("data:image/png;base64,iVBOR....")
File.open('test.png','wb') {|file| file.write x}

But then I can't open the image with a viewer, do I have to do something more?

1

4 Answers

Your problem is that you're trying to decode the 'data:image/png;base64,' prefix as Base64 data; that prefix is perfectly valid Base64 data but it is not the Base64 representation of a PNG file. The result is that your test.png file contains a bunch of nonsense followed by some bits that actually are a PNG file. Strip off the data URL prefix before decoding the PNG:

data_url = "data:image/png;base64,iVBOR...."
png = Base64.decode64(data_url['data:image/png;base64,'.length .. -1])
File.open('test.png', 'wb') { |f| f.write(png) }
7

mu_is_too_short answer is pretty close, but it assumes that base64 stream will contain PNG data. This is not always the case so I suggest to use mime types library to establish correct file extension:

REGEXP = /\Adata:([-\w]+\/[-\w\+\.]+)?;base64,(.*)/m
data_uri_parts = data_url.match(REGEXP) || []
extension = MIME::Types[data_uri_parts[1]].first.preferred_extension
file_name = "myfilename.#{extension}"
File.open(file_name, 'wb') do |file| file.write(Base64.decode64(data_uri_parts[2]))
end

Instead of using a Regexp, you can also make use of the simple String#index method.

Returns the index of the first occurrence of the given substring or pattern (regexp) in str. Returns nil if not found.

If you have a reasonably sane data source (like JavaScript's .toDataURL() on a canvas), you can rely on the fact that common mimetypes will not contain commas.

dataURL = "data:image/png;base64,iVBOR...."
start = dataURL.index(',') + 1 # .index used here
x = Base64.decode64 dataURL[start..-1]
File.open('test.png','wb') {|file| file.write x}

If you're working with a free-form user file upload, beware that a few uncommon mime types do contain commas (e.g.: text/x-java-source,java). You can use the more conservative:

start = dataURL.index(';base64,') + 8

If you don't know if you have unprefixed base64 or data URL base64, you can use #index as test:

start = dataURL.index ';base64,'
dataURL = dataURL[(start+8)..-1] if start
x = Base64.decode64 dataURL

that's a little script about how to open base64 image,vacio.txt is the file when i have the base64 text.

require 'base64'
entry="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQE....."
File.open("vacio.txt","r") do |fichero| while linea=fichero.gets regex=/(data:image\/\D*\d*,)/ m=regex.match(linea) png=Base64.decode64(linea[m.to_s.length .. -1]) File.open('test.jpeg','wb'){|f|f.write(png)} end
end 

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

You Might Also Like