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

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.

Sarah Jenkins

Sarah Jenkins

Senior Technology Editor & AI Specialist

Sarah Jenkins is a veteran tech journalist with over 12 years of experience covering artificial intelligence, mobile innovations, and digital ethics. Her insights have appeared in leading technology publications worldwide.

Share this article
Twitter Facebook Pinterest