La atob
fonction décode une chaîne encodée en Base64 en une nouvelle chaîne avec un caractère pour chaque octet des données binaires.
const byteCharacters = atob(b64Data);
Le point de code de chaque caractère (charCode) sera la valeur de l'octet. Nous pouvons créer un tableau de valeurs d'octets en appliquant ceci en utilisant la .charCodeAt
méthode pour chaque caractère de la chaîne.
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
Vous pouvez convertir ce tableau de valeurs d'octets en un tableau d'octets typé réel en le passant au Uint8Array
constructeur.
const byteArray = new Uint8Array(byteNumbers);
Celui-ci peut à son tour être converti en BLOB en l'enveloppant dans un tableau et en le transmettant au Blob
constructeur.
const blob = new Blob([byteArray], {type: contentType});
Le code ci-dessus fonctionne. Cependant, les performances peuvent être améliorées un peu en traitant les byteCharacters
plus petites tranches, plutôt que toutes à la fois. Dans mes tests approximatifs, 512 octets semblent être une bonne taille de tranche. Cela nous donne la fonction suivante.
const b64toBlob = (b64Data, contentType='', sliceSize=512) => {
const byteCharacters = atob(b64Data);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
const slice = byteCharacters.slice(offset, offset + sliceSize);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, {type: contentType});
return blob;
}
const blob = b64toBlob(b64Data, contentType);
const blobUrl = URL.createObjectURL(blob);
window.location = blobUrl;
Exemple complet:
const b64toBlob = (b64Data, contentType='', sliceSize=512) => {
const byteCharacters = atob(b64Data);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
const slice = byteCharacters.slice(offset, offset + sliceSize);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, {type: contentType});
return blob;
}
const contentType = 'image/png';
const b64Data = 'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==';
const blob = b64toBlob(b64Data, contentType);
const blobUrl = URL.createObjectURL(blob);
const img = document.createElement('img');
img.src = blobUrl;
document.body.appendChild(img);
Voici une méthode plus minimale sans dépendances ni bibliothèques.
Il nécessite la nouvelle API d'extraction. ( Puis-je l'utiliser? )
Avec cette méthode, vous pouvez également obtenir facilement un ReadableStream, ArrayBuffer, du texte et du JSON.
En tant que fonction:
J'ai fait un test de performance simple vers la version de synchronisation ES6 de Jeremy.
La version de synchronisation bloquera l'interface utilisateur pendant un certain temps. garder l'outil devtool ouvert peut ralentir les performances de récupération
Afficher l'extrait de code
la source
createObjectURL
au lieu de,readAsDataURL
c'est beaucoup mieux par exemple. Et si vous téléchargez des fichiers en utilisant ajax, choisissez à laFormData
place deJSON
, ou utilisez à lacanvas.toBlob
place detoDataURL
await (await fetch(imageDataURL)).blob()
await fetch(url).then(r=>r.blob())
est trieurAccess is denied.
erreur. Je suppose que lefetch
blob est exposé sous l'URL du blob - de la même manièreURL.createObjectUrl
- qui ne fonctionnera pas sur ie11. référence . Peut-être existe-t-il une solution de contournement pour utiliser la récupération avec IE11? Il semble beaucoup mieux que les autres solutions de synchronisation :)Implémentation optimisée (mais moins lisible):
la source
Pour toute prise en charge du navigateur, en particulier sur Android, vous pouvez peut-être ajouter ceci:
la source
Pour les données d'image, je le trouve plus simple à utiliser
canvas.toBlob
(asynchrone)la source
image/jpg
de la chaîne base64, puis en le passant en tant que deuxième paramètre entoBlob
fonction afin que le résultat soit du même type. En dehors de cela, je pense que c'est parfait - il économise 30% du trafic et de votre espace disque sur le serveur (par rapport à base64) et cela fonctionne bien même avec un PNG transparent.Voir cet exemple: https://jsfiddle.net/pqhdce2L/
la source
J'ai remarqué qu'Internet Explorer 11 devient incroyablement lent lors du découpage des données comme l'a suggéré Jeremy. Cela est vrai pour Chrome, mais Internet Explorer semble avoir un problème lors du transfert des données découpées au Blob-Constructor. Sur ma machine, le passage de 5 Mo de données fait planter Internet Explorer et la consommation de mémoire monte en flèche. Chrome crée le blob en un rien de temps.
Exécutez ce code pour une comparaison:
J'ai donc décidé d'inclure les deux méthodes décrites par Jeremy dans une seule fonction. Les crédits vont à lui pour cela.
la source
Pour tous les amateurs de copier-coller comme moi, voici une fonction de téléchargement préparée qui fonctionne sur Chrome, Firefox et Edge:
la source
createObjectURL
ne pas accepter un argument de 2 ...Si vous pouvez supporter d'ajouter une dépendance à votre projet, il y a le grand
blob-util
paquet npm qui fournit unebase64StringToBlob
fonction pratique . Une fois ajouté à votre,package.json
vous pouvez l'utiliser comme ceci:la source
Je publie un moyen plus déclaratif de synchronisation de la conversion Base64. Bien que l'async
fetch().blob()
soit très soigné et que j'aime beaucoup cette solution, elle ne fonctionne pas sur Internet Explorer 11 (et probablement Edge - je n'ai pas testé celui-ci), même avec le polyfill - jetez un œil à mon commentaire à Endless ' postez pour plus de détails.Prime
Si vous voulez l'imprimer, vous pouvez faire quelque chose comme:
Bonus x 2 - Ouverture d'un fichier BLOB dans un nouvel onglet pour Internet Explorer 11
Si vous pouvez effectuer un prétraitement de la chaîne Base64 sur le serveur, vous pouvez l'exposer sous une URL et utiliser le lien dans
printJS
:)la source
Voici mon code TypeScript qui peut être facilement converti en JavaScript et vous pouvez utiliser
la source
Typescript code
code n'a qu'un seul type et ce type estany
. Comme pourquoi même déranger ??La méthode avec fetch est la meilleure solution, mais si quelqu'un a besoin d'utiliser une méthode sans fetch alors la voici, car celles mentionnées précédemment ne fonctionnaient pas pour moi:
la source