Die atob
Funktion decodiert eine Base64-codierte Zeichenfolge in eine neue Zeichenfolge mit einem Zeichen für jedes Byte der Binärdaten.
const byteCharacters = atob(b64Data);
Der Codepunkt jedes Zeichens (charCode) ist der Wert des Bytes. Wir können ein Array von Bytewerten erstellen, indem wir dies mit der .charCodeAt
Methode für jedes Zeichen in der Zeichenfolge anwenden .
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
Sie können dieses Array von Bytewerten in ein real typisiertes Byte-Array konvertieren, indem Sie es an den Uint8Array
Konstruktor übergeben.
const byteArray = new Uint8Array(byteNumbers);
Dies kann wiederum in ein BLOB konvertiert werden, indem es in ein Array eingeschlossen und an den Blob
Konstruktor übergeben wird.
const blob = new Blob([byteArray], {type: contentType});
Der obige Code funktioniert. Die Leistung kann jedoch ein wenig verbessert werden, indem die byteCharacters
in kleineren Scheiben anstatt auf einmal verarbeitet werden. In meinem groben Test scheinen 512 Bytes eine gute Slice-Größe zu sein. Dies gibt uns die folgende Funktion.
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;
Vollständiges Beispiel:
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);
Hier ist eine minimalere Methode ohne Abhängigkeiten oder Bibliotheken.
Es erfordert die neue Abruf-API. ( Kann ich es benutzen? )
Mit dieser Methode können Sie auch problemlos einen ReadableStream, ArrayBuffer, Text und JSON abrufen.
Als eine Funktion:
Ich habe einen einfachen Leistungstest für Jeremys ES6-Synchronisierungsversion durchgeführt.
Die Synchronisierungsversion blockiert die Benutzeroberfläche für eine Weile. Wenn Sie das devtool offen halten, kann dies die Abrufleistung verlangsamen
Code-Snippet anzeigen
quelle
createObjectURL
stattreadAsDataURL
ist zum Beispiel viel besser. Und wenn Sie Dateien mit Ajax hochladen, wählen SieFormData
anstelle vonJSON
odercanvas.toBlob
anstelle vontoDataURL
await (await fetch(imageDataURL)).blob()
await fetch(url).then(r=>r.blob())
ist SortiererAccess is denied.
Fehlers nicht mit IE (mit Polyfill ofc) . Ich denke,fetch
macht Blob unter Blob-URLURL.createObjectUrl
verfügbar - auf die gleiche Weise - was bei ie11 nicht funktioniert. Referenz . Vielleicht gibt es eine Problemumgehung, um Fetch mit IE11 zu verwenden? Es sieht viel besser aus als andere Synchronisierungslösungen :)Optimierte (aber weniger lesbare) Implementierung:
quelle
Für die gesamte Browserunterstützung, insbesondere für Android, können Sie möglicherweise Folgendes hinzufügen:
quelle
Für Bilddaten finde ich es einfacher zu verwenden
canvas.toBlob
(asynchron)quelle
image/jpg
aus der base64-Zeichenfolge extrahieren und ihn dann als zweiten Parameter antoBlob
function übergeben, sodass das Ergebnis vom gleichen Typ ist. Abgesehen davon halte ich dies für perfekt - es spart 30% des Datenverkehrs und Ihren Speicherplatz auf dem Server (im Vergleich zu base64) und funktioniert auch mit transparentem PNG gut.Siehe dieses Beispiel: https://jsfiddle.net/pqhdce2L/
quelle
Mir ist aufgefallen, dass Internet Explorer 11 beim Schneiden der Daten unglaublich langsam wird, wie Jeremy vorgeschlagen hat. Dies gilt für Chrome, aber Internet Explorer scheint ein Problem zu haben, wenn die geschnittenen Daten an den Blob-Constructor übergeben werden. Wenn auf meinem Computer 5 MB Daten übergeben werden, stürzt der Internet Explorer ab und der Speicherverbrauch steigt. Chrome erstellt den Blob in kürzester Zeit.
Führen Sie diesen Code zum Vergleich aus:
Deshalb habe ich beschlossen, beide von Jeremy beschriebenen Methoden in eine Funktion aufzunehmen. Dafür gehen ihm Credits.
quelle
Wenn Sie es ertragen können, Ihrem Projekt eine Abhängigkeit hinzuzufügen, gibt es das großartige
blob-util
npm-Paket , das eine praktischebase64StringToBlob
Funktion bietet . Einmal zu Ihrem hinzugefügt, könnenpackage.json
Sie es wie folgt verwenden:quelle
Für alle Liebhaber von Copy-Paste wie mich gibt es hier eine gekochte Download-Funktion, die auf Chrome, Firefox und Edge funktioniert:
quelle
createObjectURL
akzeptieren kein 2. Argument ...Ich veröffentliche eine deklarativere Methode zur Synchronisierung der Base64-Konvertierung. Async
fetch().blob()
ist zwar sehr ordentlich und ich mag diese Lösung sehr, aber sie funktioniert nicht mit Internet Explorer 11 (und wahrscheinlich Edge - ich habe diese nicht getestet), selbst mit der Polyfüllung - werfen Sie einen Blick auf meinen Kommentar zu Endless ' Post für weitere Details.Bonus
Wenn Sie es drucken möchten, können Sie Folgendes tun:
Bonus x 2 - Öffnen einer BLOB-Datei in einem neuen Tab für Internet Explorer 11
Wenn Sie in der Lage sind, die Base64-Zeichenfolge auf dem Server vorzuverarbeiten, können Sie sie unter einer URL verfügbar machen und den Link in
printJS
:) verwendenquelle
Es folgt mein TypeScript-Code, der einfach in JavaScript konvertiert werden kann und den Sie verwenden können
quelle
Typescript code
Code hat nur einen SINGLE-Typ und dieser Typ istany
. Wie, warum überhaupt stören?Die Methode mit Fetch ist die beste Lösung, aber wenn jemand eine Methode ohne Fetch verwenden muss, dann ist sie hier, da die zuvor genannten für mich nicht funktioniert haben:
quelle