2009-07-21 18 views
40

Estoy integrando mi aplicación Ruby on Rails con un sistema de envío usps. Una vez que realiza una solicitud de franqueo, paga ese franqueo y no es reembolsable.Cómo guardar una cadena base64 como una imagen usando ruby ​​

Las solicitudes de franqueo le devolverán una respuesta xml que incluye una cadena base64, que es la etiqueta de envío.

Soy capaz de mostrar la etiqueta de envío en una vista, sin embargo para hacerlo infalible, me gustaría poder guardar esa cadena base64 como una imagen en mi servidor en caso de que algo le pase a la etiqueta de envío entre generación (pagando) y envío por correo para que pueda ser reimpreso sin comprar uno nuevo.

Mis primeros pensamientos fueron los siguientes

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

Ni trabajo.

Respuesta

77

Cuando se escriben datos binarios en un archivo, como en el caso de una imagen, el uso de IO # puts es peligroso y es mejor evitarlo. Debería escribir en modo binario, que es casi irrelevante en plataformas LF únicas como UNIX o OS X, pero es imprescindible en CRLF como Windows. IO # puts también agrega una nueva línea al final del archivo que no es válida.

El mejor enfoque es especificar la bandera correcta en la convocatoria abierta:

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

Por ejemplo, véase el comentario de la página de documentación abierto # IO:

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

+1

Este trabajo es perfecto. Gracias por las explicaciones y enlaces. – Ricky

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

que la imagen kan uso como archivo Photo.new (imagen: Imagen) Después #save clip useng en el modelo Foto

10

Otras respuestas son bastante cerca, pero por lo general asumen que base64 stream contendrá datos PNG. Este no es siempre el caso, así que sugiero usar la biblioteca de tipos mime para establecer la extensión de archivo correcta:

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 
Cuestiones relacionadas