如何使用Ruby将Base64字符串保存为图像

64

我正在将我的 Ruby on Rails 应用程序与 USPS 运输系统集成。一旦您发出邮资请求,您将支付该邮资费用,且该费用不可退款。

邮资请求将返回一个 XML 响应,其中包括一个 base64 字符串,即运输标签。

我能够在视图中呈现运输标签,但为了使其更加安全可靠,我想能够将该 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))
}

都不起作用。

4个回答

107

在写二进制数据到文件时,比如图片,你不能使用像 IO#puts 这样的文本打印工具。

你需要确保两件事情:

  • 你需要以二进制模式进行写入,以避免可能的 LF 转 CRLF 扩展。
  • 你必须使用 write 而不是 puts,因为 write 可以处理任意数据,而 puts(字面意思是 “放置字符串”)仅适用于文本。

将它们结合起来,你会得到:

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

1
这项工作很完美。感谢您的解释和链接。 - Ricky
@AhmedSalah 不确定你的意思。这对于base64编码的数据仍然有效。 - tadman
@tadman 我正在尝试保存PNG图像,但是图像文件已损坏,例如Image Viewer显示“致命错误读取PNG图像文件:不是PNG文件” 此外,我在这里有类似的问题 https://dev59.com/Jbroa4cB1Zd3GeqPhk90 - Ahmed Salah

26

其他答案都比较接近,但通常假设base64编码的流将包含PNG数据。但实际情况并非总是如此,因此我建议使用mime types库来确定正确的文件扩展名:

其他答案都相当接近,但通常会假设base64编码的流将包含PNG数据。不过,并非总是这样,因此我建议使用mime types库来确定正确的文件扩展名:

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

REGEXP = /\Adata:([-\w]+/[-\w+.]+)?;base64,(.*)/m语法错误异常:(byebug):1:未终止的正则表达式遇到文件结尾 ...= /\Adata:([-\w]+/[-\w+.]+)? - Muhammad Umair
只需将 REGEXP 更改为小写 - regexp。这样就可以消除错误了。 - Qasim

8
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)

在您可以将图像用作文件之后

Photo.new(image: image) # 在 Photo 模型中使用 paperclip 进行保存


1
你为什么要使用 'RMagick'?解决方案的其余部分并没有使用它。 - Mark Ellul
这就是我需要的。 - DivinesLight

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接