J'ai une communication webSocket, je reçois une chaîne encodée en base64, je la convertis en uint8 et je travaille dessus, mais maintenant j'ai besoin de la renvoyer, j'ai le tableau uint8, et j'ai besoin de le convertir en chaîne base64, pour pouvoir l'envoyer. Comment puis-je faire cette conversion ?
Réponses
Trop de publicités?function Uint8ToBase64(u8Arr){
var CHUNK_SIZE = 0x8000; //arbitrary number
var index = 0;
var length = u8Arr.length;
var result = '';
var slice;
while (index < length) {
slice = u8Arr.subarray(index, Math.min(index + CHUNK_SIZE, length));
result += String.fromCharCode.apply(null, slice);
index += CHUNK_SIZE;
}
return btoa(result);
}
Vous pouvez utiliser cette fonction si vous avez un très grand Uint8Array. Ceci est pour Javascript, peut être utile dans le cas de FileReader readAsArrayBuffer.
JS pur - sans corde middlestep (sans btoa)
Dans la solution ci-dessous, j'ai omis la conversion en chaîne. L'IDEA est le suivant :
- joindre 3 octets (3 éléments du tableau) et vous obtenez 24 bits
- diviser 24bits en quatre nombres de 6 bits (qui prennent des valeurs de 0 à 63)
- utiliser ces chiffres comme index dans l'alphabet base64
- cas particulier : lorsque le tableau d'octets d'entrée la longueur n'est pas divisée par 3, il faut ajouter
=
o==
au résultat
La solution ci-dessous fonctionne sur des morceaux de 3 octets, elle est donc adaptée aux grands tableaux. Solution similaire pour convertir base64 en tableau binaire (sans atob
) est ICI
function bytesArrToBase64(arr) {
const abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; // base64 alphabet
const bin = n => n.toString(2).padStart(8,0); // convert num to 8-bit binary string
const l = arr.length
let result = '';
for(let i=0; i<=(l-1)/3; i++) {
let c1 = i*3+1>=l; // case when "=" is on end
let c2 = i*3+2>=l; // case when "=" is on end
let chunk = bin(arr[3*i]) + bin(c1? 0:arr[3*i+1]) + bin(c2? 0:arr[3*i+2]);
let r = chunk.match(/.{1,6}/g).map((x,j)=> j==3&&c2 ? '=' :(j==2&&c1 ? '=':abc[+('0b'+x)]));
result += r.join('');
}
return result;
}
// ----------
// TEST
// ----------
let test = "Alice's Adventure in Wondeland.";
let testBytes = [...test].map(c=> c.charCodeAt(0) );
console.log('test string:', test);
console.log('bytes:', JSON.stringify(testBytes));
console.log('btoa ', btoa(test));
console.log('bytesArrToBase64', bytesArrToBase64(testBytes));
Depuis btoa
ne fonctionne qu'avec les chaînes de caractères, nous pouvons transformer les Uint8Array en chaînes de caractères avec String.fromCharCode
:
const toBase64 = uInt8Array => btoa(String.fromCharCode(...uInt8Array));
La documentation de MDN bien couvrir btoa.
Puisque vous disposez déjà de données binaires, vous pouvez convertir votre Uint8Array en chaîne de caractères ASCII et invoquer l'opération suivante btoa
sur cette chaîne.
function encodeBase64Bytes(bytes: Uint8Array): string {
return btoa(
bytes.reduce((acc, current) => acc + String.fromCharCode(current), "")
);
}
Complexité avec btoa
se présente lorsque vous devez encoder des chaînes JS arbitraires, qui peuvent occuper plus d'un seul octet, telles que "