Retrieving Binary File Content Using JavaScript, Base64 Encode It and Reverse-Decode It Using Python

Retrieving binary file content using Javascript, base64 encode it and reverse-decode it using Python

So I'm answering to myself — and sorry for that — but I think it might be useful for someone as lost as I was ;)

So you have to use ArrayBuffer and set the responseType property of your XMLHttpRequest object instance to arraybuffer for retrieving a native array of Bytes, which can be converted to base64 using the following convenient function (found there, author may be blessed here):

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
}

So here's a working code:

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();

This will log a valid base64 encoded string representing the binary file contents.

Edit: For older browsers not having access to ArrayBuffer and having btoa() failing on encoding characters, here's another way to get a base64 encoded version of any binary:

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')));

Hope this helps others as it did for me.

Base64 encoding bytes in python, decoding in javascript doesn't return the original bytes

atob will try decoding the bytes as text, instead of encoding the bytes into something like the b'...' in Python.

You asked: How can I decode it with javascript and get the original bytes as a string? But I believe, you should just use the bytes rather than convert it to a string.

So I tried my base-64 decoding tool. I think the byte array it returns meets your requirement (as ac does mean 172): [172, 209, 37, 61, 221, 231, 24, 143, 188, 68, 114, 122, 163, 138, 172, 141, 84, 136, 9, 207, 55, 10, 111, 251, 162, 151, 67, 73, 133, 228, 58, 242, 47, 216, 97, 181, 210, 130, 168, 206, 2, 68, 102, 208, 63, 6, 114, 101, 62, 176, 148, 93, 59, 126, 255, 0, 99, 86, 181, 227, 232, 209, 160, 110].

In the tool I used the package js-base64 to decode it. But it was developed years ago, I don't know whether there are better solutions now.

convert binary data to base-64 javaScript

My problem is solved . I use dropzone plugin to get the response from server and because of this I get binary data as a text reponse and it make my problems. I just go to dropzone.js and change 2 minor things to get the response in type of arraybuffer :

        xhr.responseType = 'arraybuffer'; ( line 1246)

This is new line to get the response in type of arrayBuffer, and then create a Blob object from the arraybuffer response .

          response = xhr.response; (line 1305 ) 

Change it to get response inseted TextRrsponse..

I hope that it will help somebody...
Thanks everyone !

How to encode and decode docx file using base64 in python

You need to add filename argument to download_button function

import base64
import streamlit as st

data = open("test.docx", "rb").read()
encoded = base64.b64encode(data)
decoded = base64.b64decode(encoded)

st.download_button('Download Here', decoded, "decoded_file.docx")

Python 3 and base64 encoding of a binary file

From the base64 package doc:

base64.encodestring:

"Encode the bytes-like object s, which can contain arbitrary binary data, and return bytes containing the base64-encoded data, with newlines (b"\n") inserted after every 76 bytes of output, and ensuring that there is a trailing newline, as per RFC 2045 (MIME)."

You want to use

base64.b64encode:

"Encode the bytes-like object s using Base64 and return the encoded bytes."

Example:

import base64

with open("test.zip", "rb") as f:
encodedZip = base64.b64encode(f.read())
print(encodedZip.decode())

The decode() will convert the binary string to text.

Encode/Decode a EXE file into base64 in Python

First of all, when saving your encoded version don't open the ".txt" in binary mode: it is a string representation.

Then just read the encoded file

ft = open('testoutput.txt', 'r')
encoded = ft.read()

And then write it to the final destination

with open("testoutput1.exe", "wb") as exe:
exe.write(base64.b64decode(encoded))

Note: this time you must open the file for writing in binary mode ("wb"); and you don't want to convert the content to a string with str().

JavaScript Base 64 Decoding Binary Data Doesn't Work

Summary

Your MD5 library is OK, your base64 library is broken.

Both your JavaScript Base64 library and MD5 library are not working correctly.

  1. I have created and verified a ZIP file of 15097 bytes.

    MD5 sum: a9de6b8e5a9173140cb46d4b3b31b67c
  2. I have base64-encoded this file: http://pastebin.com/2rfdTzYT (20132 bytes).
  3. Verify the length of the base64 file at pastebin, using the following JavaScript snippet:

    document.querySelector('.de1').textContent.replace(/\s/g,'').length;
  4. Base64-decode the file properly using atob, and verify the size:

    window.b64_str = document.querySelector('.de1').textContent.replace(/\s/g,'');
    console.log( atob(window.b64_str).length ); /* 15097 */
  5. I verified that both files were exactly equal using the Hexdump JavaScript library, and the xxd UNIX command (available as EXE file for Windows).

Using your Base64 decoder, I get a string with the size of 8094. That is not 15097!
During my tests, I discovered that the atob method returned incorrect bytes after certain byte sequences, including carriage returns. I have not yet found a solution to this.

Your MD5 library is OK.

Convert binary data to base64 with javascript

Try the btoa function:

   var data = btoa(r);


Related Topics



Leave a reply



Submit