Ruby on rails 如何使用ruby将base64字符串保存为图像

Ruby on rails 如何使用ruby将base64字符串保存为图像,ruby-on-rails,ruby,image,file-io,base64,Ruby On Rails,Ruby,Image,File Io,Base64,我正在将我的Ruby on Rails应用程序与usps配送系统集成。一旦你提出邮资要求,你就要支付邮资,邮资是不可退还的 邮资请求将返回一个包含base64字符串的xml响应,该字符串是发货标签 我能够在视图中呈现装运标签,但是为了使其万无一失,我希望能够将base64字符串保存为服务器上的图像,以防在生成(付费)和邮寄之间装运标签发生问题,因此可以在不购买新标签的情况下重新打印 我最初的想法如下 # Attempt 1 File.open('shipping_label.gif', 'w+'

我正在将我的Ruby on Rails应用程序与usps配送系统集成。一旦你提出邮资要求,你就要支付邮资,邮资是不可退还的

邮资请求将返回一个包含base64字符串的xml响应,该字符串是发货标签

我能够在视图中呈现装运标签,但是为了使其万无一失,我希望能够将base64字符串保存为服务器上的图像,以防在生成(付费)和邮寄之间装运标签发生问题,因此可以在不购买新标签的情况下重新打印

我最初的想法如下

# 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))
}

两者都不起作用

在将二进制数据写入文件(例如图像)时,不能使用诸如
IO\puts
之类的文本打印工具

您需要确保两件事:

  • 您需要以二进制模式写入,以避免任何可能的LF到CRLF扩展
  • 您必须使用
    write
    而不是
    put
    ,因为
    write
    可以处理任意数据,但
    put
    (字面意思是“put string”)仅用于文本
结合这些,您可以得到:

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

如果需要将其写入图像,请通过rmagick gem使用imagemagick

之后可以将图像用作文件
Photo.new(image:image)#在照片模型中使用回形针保存

其他答案非常接近,但通常假设base64流将包含PNG数据。情况并非总是如此,因此我建议使用mime类型库来建立正确的文件扩展名:

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

这件工作做得很好。谢谢你的解释和链接。@AhmedSalah不知道你的意思。这对base64编码数据仍然有效。@tadman我正试图保存PNG图像,但图像文件已损坏,例如图像查看器说“读取PNG图像文件时出现致命错误:不是PNG文件”,我也有类似的Q here REGEXP=/\Adata:([-\w]+\/[-\w\+\.]+)?;base64,(.*)/m语法错误异常:(byebug):1:未终止的regexp遇到文件结尾…=/\Adata:([-\w]+\/[-\w\+\.]+)?为什么需要“RMagick”?解决方案的其余部分不使用它
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