How to save a base64 string as an image using ruby

2019-01-10 11:07发布

I'm integrating my Ruby on Rails app with a usps shipping system. Once you make a postage request, you pay for that postage and it's nonrefundable.

Postage requests will return you an xml response including a base64 string, which is the shipping label.

I'm able to render the shipping label in a view, however to make it foolproof, I would like to be able to save that base64 string as an image on my server in the event that something happens to the shipping label between generation (paying for it) and mailing so it may be reprinted without buying a new one.

My first thoughts were as follows

# Attempt 1
File.open('shipping_label.gif', 'w+') {|f|
    f.puts Base64.decode64(base_64_encoded_data)
}

# Attempt 2
File.open('shipping_label.gif', 'w+') {|f|
    f.puts Base64.decode64(Base64.decode64(base_64_encoded_data))
}

Neither work.

4条回答
时光不老,我们不散
2楼-- · 2019-01-10 11:26

Other answers are pretty close, but usually assume 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
查看更多
做自己的国王
3楼-- · 2019-01-10 11:38

When writing binary data to a file, such as is the case with an image, using IO#puts is hazardous and best avoided. You should be writing in binary mode, which is mostly irrelevant on LF-only platforms such as UNIX or OS X, but is imperative on CRLF ones such as Windows. IO#puts also appends a newline at the end of the file which is invalid.

The best approach is to specify the correct flag on the open call:

File.open('shipping_label.gif', 'wb') do |f|
  f.write(Base64.decode64(base_64_encoded_data))
end

For example, see the comment on the IO#open documentation page:

http://apidock.com/ruby/IO/open/class

查看更多
别忘想泡老子
4楼-- · 2019-01-10 11:44

If you need to write it to an image then use imagemagick through the rmagick gem.

http://rmagick.rubyforge.org/

查看更多
贼婆χ
5楼-- · 2019-01-10 11:48
require 'RMagick'
data = params[:image_text]# code like this  data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABPUAAAI9CAYAAABSTE0XAAAgAElEQVR4Xuy9SXPjytKm6ZwnUbNyHs7Jc7/VV9bW1WXWi9q
image_data = Base64.decode64(data['data:image/png;base64,'.length .. -1])
new_file=File.new("somefilename.png", 'wb')
new_file.write(image_data)

After you kan use image as file Photo.new(image: image)#save useng paperclip in Photo model

查看更多
登录 后发表回答