I need an efficient (read native) way to convert an ArrayBuffer
to a base64 string which needs to be used on a multipart post.
function _arrayBufferToBase64( buffer ) {
var binary = '';
var bytes = new Uint8Array( buffer );
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode( bytes[ i ] );
}
return window.btoa( binary );
}
but, non-native implementations are faster eg https://gist.github.com/958841 see http://jsperf.com/encoding-xhr-image-data/6
Updated benchmarks: https://jsben.ch/wnaZC
This works fine for me:
var base64String = btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)));
In ES6, the syntax is a little simpler:
const base64String = btoa(String.fromCharCode(...new Uint8Array(arrayBuffer)));
As pointed out in the comments, this method may result in a runtime error in some browsers when the ArrayBuffer
is large. The exact size limit is implementation dependent in any case.
For those who like it short, here's an other one using Array.reduce
which will not cause stack overflow:
var base64 = btoa(
new Uint8Array(arrayBuffer)
.reduce((data, byte) => data + String.fromCharCode(byte), '')
);
There is another asynchronous way use Blob and FileReader.
I didn't test the performance. But it is a different way of thinking.
function arrayBufferToBase64( buffer, callback ) {
var blob = new Blob([buffer],{type:'application/octet-binary'});
var reader = new FileReader();
reader.onload = function(evt){
var dataurl = evt.target.result;
callback(dataurl.substr(dataurl.indexOf(',')+1));
};
reader.readAsDataURL(blob);
}
//example:
var buf = new Uint8Array([11,22,33]);
arrayBufferToBase64(buf, console.log.bind(console)); //"CxYh"
var blob = new Blob([arrayBuffer])
var reader = new FileReader();
reader.onload = function(event){
var base64 = event.target.result
};
reader.readAsDataURL(blob);
I used this and works for me.
function arrayBufferToBase64( buffer ) {
var binary = '';
var bytes = new Uint8Array( buffer );
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode( bytes[ i ] );
}
return window.btoa( binary );
}
function base64ToArrayBuffer(base64) {
var binary_string = window.atob(base64);
var len = binary_string.length;
var bytes = new Uint8Array( len );
for (var i = 0; i < len; i++) {
bytes[i] = binary_string.charCodeAt(i);
}
return bytes.buffer;
}
My recommendation for this is to NOT use native btoa
strategies—as they don't correctly encode all ArrayBuffer
's…
rewrite the DOMs atob() and btoa()
Since DOMStrings are 16-bit-encoded strings, in most browsers calling window.btoa on a Unicode string will cause a Character Out Of Range exception if a character exceeds the range of a 8-bit ASCII-encoded character.
While I have never encountered this exact error, I have found that many of the ArrayBuffer
's I have tried to encode have encoded incorrectly.
I would either use MDN recommendation or gist.
Below are 2 simple functions for converting Uint8Array to Base64 String and back again
arrayToBase64String(a) {
return btoa(String.fromCharCode(...a));
}
base64StringToArray(s) {
let asciiString = atob(s);
return new Uint8Array([...asciiString].map(char => char.charCodeAt(0)));
}
The OP did not specify the Running Enviroment but if you are using Node.JS there is a very simple way to do such thing.
Accordig with the official Node.JS docs https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings
// This step is only necessary if you don't already have a Buffer Object
const buffer = Buffer.from(yourArrayBuffer);
const base64String = buffer.toString('base64');
Also, If you are running under Angular for example, the Buffer Class will also be made available in a Browser Environment.
If you're okay with adding a library, base64-arraybuffer :
yarn add base64-arraybuffer
then:
encode(buffer)
- Encodes ArrayBuffer into base64 string decode(str)
- Decodes base64 string to ArrayBuffer You can derive a normal array from the ArrayBuffer
by using Array.prototype.slice
. Use a function like Array.prototype.map
to convert bytes in to characters and join
them together to forma string.
function arrayBufferToBase64(ab){
var dView = new Uint8Array(ab); //Get a byte view
var arr = Array.prototype.slice.call(dView); //Create a normal array
var arr1 = arr.map(function(item){
return String.fromCharCode(item); //Convert
});
return window.btoa(arr1.join('')); //Form a string
}
This method is faster since there are no string concatenations running in it.
ABtoB64(ab) {
return new Promise(res => {
const fr = new FileReader();
fr.onload = ({target: {result: s}}) => res(s.slice(s.indexOf(';base64,') + 8));
fr.readAsDataURL(new Blob([ab]));
});
}
asynchronous method using file reader.
In the Browser suggested solutions with btoa
seem fine. But in Node.js btoa is deprecated
It is recommended to use buffer.toString(encoding)
like
const myString = buffer.toString("base64")
i use TextDecode
api to convert it to normal text and then convert it to Base64
const uint = new Uint8Array([ 73, 32, 108, 111, 118, 101, 32, 121, 111, 117 ]).buffer
const decoder = new TextDecoder()
const decodedText = decoder.decode(uint)
const base64Code = btoa(decodedText)
This worked for me:
Buffer.from(myArrayBuffer).toString("base64");
使用uint8-to-b64
包在浏览器和 Node.js 中进行编码/解码
By my side, using Chrome navigator, I had to use DataView() to read an arrayBuffer
function _arrayBufferToBase64( tabU8A ) {
var binary = '';
let lecteur_de_donnees = new DataView(tabU8A);
var len = lecteur_de_donnees.byteLength;
var chaine = '';
var pos1;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode( lecteur_de_donnees.getUint8( i ) );
}
chaine = window.btoa( binary )
return chaine;}
function _arrayBufferToBase64(uarr) {
var strings = [], chunksize = 0xffff;
var len = uarr.length;
for (var i = 0; i * chunksize < len; i++){
strings.push(String.fromCharCode.apply(null, uarr.subarray(i * chunksize, (i + 1) * chunksize)));
}
return strings.join("");
}
This is better, if you use JSZip for unpack archive from string
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.