online - Recuperar el contenido del archivo binario utilizando Javascript, base64 codificarlo y decodificarlo inversamente usando Python
decodificar imagen base64 javascript (1)
Así que estoy respondiendo a mí mismo, y lo siento por eso, pero creo que podría ser útil para alguien tan perdido como yo lo estaba;)
Entonces debe usar ArrayBuffer y establecer la propiedad responseType
de su instancia de objeto XMLHttpRequest
en arraybuffer
para recuperar una matriz nativa de Bytes, que se puede convertir a base64 usando la siguiente función conveniente (aquí se encuentra, el autor puede ser bendecido aquí):
function base64ArrayBuffer(arrayBuffer) {
var base64 = ''''
var encodings = ''ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/''
var bytes = new Uint8Array(arrayBuffer)
var byteLength = bytes.byteLength
var byteRemainder = byteLength % 3
var mainLength = byteLength - byteRemainder
var a, b, c, d
var chunk
// Main loop deals with bytes in chunks of 3
for (var i = 0; i < mainLength; i = i + 3) {
// Combine the three bytes into a single integer
chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]
// Use bitmasks to extract 6-bit segments from the triplet
a = (chunk & 16515072) >> 18 // 16515072 = (2^6 - 1) << 18
b = (chunk & 258048) >> 12 // 258048 = (2^6 - 1) << 12
c = (chunk & 4032) >> 6 // 4032 = (2^6 - 1) << 6
d = chunk & 63 // 63 = 2^6 - 1
// Convert the raw binary segments to the appropriate ASCII encoding
base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d]
}
// Deal with the remaining bytes and padding
if (byteRemainder == 1) {
chunk = bytes[mainLength]
a = (chunk & 252) >> 2 // 252 = (2^6 - 1) << 2
// Set the 4 least significant bits to zero
b = (chunk & 3) << 4 // 3 = 2^2 - 1
base64 += encodings[a] + encodings[b] + ''==''
} else if (byteRemainder == 2) {
chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1]
a = (chunk & 64512) >> 10 // 64512 = (2^6 - 1) << 10
b = (chunk & 1008) >> 4 // 1008 = (2^6 - 1) << 4
// Set the 2 least significant bits to zero
c = (chunk & 15) << 2 // 15 = 2^4 - 1
base64 += encodings[a] + encodings[b] + encodings[c] + ''=''
}
return base64
}
Así que aquí hay un código de trabajo:
var xhr = new XMLHttpRequest();
xhr.open(''GET'', ''http://some.tld/favicon.png'', false);
xhr.responseType = ''arraybuffer'';
xhr.onload = function(e) {
console.log(base64ArrayBuffer(e.currentTarget.response));
};
xhr.send();
Esto registrará una cadena codificada base64 válida que representa el contenido del archivo binario.
Editar: para navegadores más antiguos que no tienen acceso a ArrayBuffer
y tienen btoa()
fallando en la codificación de caracteres, aquí hay otra manera de obtener una versión codificada en base64 de cualquier binario:
function getBinary(file){
var xhr = new XMLHttpRequest();
xhr.open("GET", file, false);
xhr.overrideMimeType("text/plain; charset=x-user-defined");
xhr.send(null);
return xhr.responseText;
}
function base64Encode(str) {
var CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var out = "", i = 0, len = str.length, c1, c2, c3;
while (i < len) {
c1 = str.charCodeAt(i++) & 0xff;
if (i == len) {
out += CHARS.charAt(c1 >> 2);
out += CHARS.charAt((c1 & 0x3) << 4);
out += "==";
break;
}
c2 = str.charCodeAt(i++);
if (i == len) {
out += CHARS.charAt(c1 >> 2);
out += CHARS.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
out += CHARS.charAt((c2 & 0xF) << 2);
out += "=";
break;
}
c3 = str.charCodeAt(i++);
out += CHARS.charAt(c1 >> 2);
out += CHARS.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
out += CHARS.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
out += CHARS.charAt(c3 & 0x3F);
}
return out;
}
console.log(base64Encode(getBinary(''http://www.google.fr/images/srpr/logo3w.png'')));
Espero que esto ayude a otros como lo hizo conmigo.
Estoy intentando descargar un archivo binario usando XMLHttpRequest
(usando un Webkit reciente) y codificar base64 sus contenidos usando esta sencilla función:
function getBinary(file){
var xhr = new XMLHttpRequest();
xhr.open("GET", file, false);
xhr.overrideMimeType("text/plain; charset=x-user-defined");
xhr.send(null);
return xhr.responseText;
}
function base64encode(binary) {
return btoa(unescape(encodeURIComponent(binary)));
}
var binary = getBinary(''http://some.tld/sample.pdf'');
var base64encoded = base64encode(binary);
Como nota al margen, todo lo anterior es material estándar de Javascript, incluyendo btoa()
y encodeURIComponent()
: https://developer.mozilla.org/en/DOM/window.btoa
Esto funciona bastante bien, e incluso puedo decodificar los contenidos de base64 usando Javascript:
function base64decode(base64) {
return decodeURIComponent(escape(atob(base64)));
}
var decodedBinary = base64decode(base64encoded);
decodedBinary === binary // true
Ahora, quiero decodificar los contenidos codificados en base64 usando Python que consume alguna cadena JSON para obtener el valor de cadena codificado en base64. Ingenuamente, esto es lo que hago:
import urllib
import base64
# ... retrieving of base64 encoded string through JSON
base64 = "77+9UE5HDQ……………oaCgA="
source_contents = urllib.unquote(base64.b64decode(base64))
destination_file = open(destination, ''wb'')
destination_file.write(source_contents)
destination_file.close()
Pero el archivo resultante no es válido, parece que la operación se ha enviado a mensajería con UTF-8, codificación o algo que todavía no está claro para mí.
Si trato de decodificar los contenidos UTF-8 antes de ponerlos en el archivo de destino, aparece un error:
import urllib
import base64
# ... retrieving of base64 encoded string through JSON
base64 = "77+9UE5HDQ……………oaCgA="
source_contents = urllib.unquote(base64.b64decode(base64)).decode(''utf-8'')
destination_file = open(destination, ''wb'')
destination_file.write(source_contents)
destination_file.close()
$ python test.py
// ...
UnicodeEncodeError: ''ascii'' codec can''t encode character u''/ufffd'' in position 0: ordinal not in range(128)
Como nota al margen, aquí hay una captura de pantalla de dos representaciones textuales de un mismo archivo; a la izquierda: el original; a la derecha: el creado a partir de la cadena descodificada en base64: http://cl.ly/0U3G34110z3c132O2e2x
¿Hay algún truco conocido para eludir estos problemas con la codificación al intentar recrear el archivo? ¿Cómo lograría esto usted mismo?
Cualquier ayuda o pista muy apreciada :)