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.
- I have created and verified a ZIP file of 15097 bytes.
MD5 sum:a9de6b8e5a9173140cb46d4b3b31b67c
- I have base64-encoded this file: http://pastebin.com/2rfdTzYT (20132 bytes).
- Verify the length of the base64 file at pastebin, using the following JavaScript snippet:
document.querySelector('.de1').textContent.replace(/\s/g,'').length;
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 */- I verified that both files were exactly equal using the
Hexdump
JavaScript library, and thexxd
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
Triggering a JavaScript Click() Event at Specific Coordinates
How to Determine If an Image Has Loaded, Using JavaScript/Jquery
Multiple Path Names for a Same Component in React Router
React Router Doesn't Work in Aws S3 Bucket
How to Write Your Own Custom Legends for Google Line Chart/ Google Line Chart Legend Manipulation
Setting Multiple Attributes for an Element at Once with JavaScript
Javascript: Clear All Timeouts
How to Declare a Global Variable in a .Js File
Add Onclick Event to Newly Added Element in JavaScript
Why Define an Anonymous Function and Pass It Jquery as the Argument
Merge Two Arrays So That the Values Alternate
Get Event Listeners Attached to Node Using Addeventlistener
How to Trigger a Link's (Or Any Element'S) Click Event Through JavaScript
Can You Do Desktop Development Using JavaScript
How to Flatten Nested Array in JavaScript
Use $Http Inside Custom Provider in App Config, Angular.Js