Blob von DataURL?

85

Mit FileReader's readAsDataURL()kann ich beliebige Daten in eine Daten-URL umwandeln. Gibt es eine Möglichkeit, eine Daten-URL Blobmithilfe der integrierten Browser-APIs wieder in eine Instanz zu konvertieren ?

Shane Holloway
quelle

Antworten:

143

Benutzer Matt hat vor einem Jahr den folgenden Code vorgeschlagen ( Wie konvertiere ich dataURL in ein Dateiobjekt in Javascript? ), Der Ihnen helfen könnte

EDIT: Wie einige Kommentatoren berichteten, ist BlobBuilder vor einiger Zeit veraltet. Dies ist der aktualisierte Code:

function dataURItoBlob(dataURI) {
  // convert base64 to raw binary data held in a string
  // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
  var byteString = atob(dataURI.split(',')[1]);

  // separate out the mime component
  var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]

  // write the bytes of the string to an ArrayBuffer
  var ab = new ArrayBuffer(byteString.length);

  // create a view into the buffer
  var ia = new Uint8Array(ab);

  // set the bytes of the buffer to the correct values
  for (var i = 0; i < byteString.length; i++) {
      ia[i] = byteString.charCodeAt(i);
  }

  // write the ArrayBuffer to a blob, and you're done
  var blob = new Blob([ab], {type: mimeString});
  return blob;

}
devnull69
quelle
2
Hinweis: Laut MDN ist BlobBuilder jetzt veraltet. Keine Ahnung seit wann. (Ich weiß, dass dies eine ziemlich alte Frage und Antwort ist, nur um sie ein wenig auf dem neuesten Stand zu halten.) Stattdessen akzeptiert der Blob eine Reihe von Teilen als ersten Parameter seines Konstruktors.
Kiruse
8
Sie können den BlobBuilder als den Blob ersetzen. var blob = neuer Blob ([ab], {Typ: mimeString}); Blob zurückgeben;
Danil Chernokalov
4
Die doppelte Aufteilung scheint etwas verschwenderisch zu sein, da dies eine sehr große Zeichenfolge sein könnte.
Jesse Crossen
2
Welche Rolle spielt die Variable "ia" - ihr wird ein Wert zugewiesen, der jedoch niemals zur Bildung des Blobs verwendet wird. Warum?
Blaze
9
Blob der Baumeister? :)
Peter Wone
40

Wie @Adria Methode, aber mit Fetch API und nur kleiner [ caniuse? ]
Sie müssen nicht über den Mimetyp nachdenken, da der Blob-Antworttyp sofort funktioniert

Warnung: Kann gegen die Content Security Policy (CSP) verstoßen
... wenn Sie dieses Material verwenden

var url = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="

fetch(url)
.then(res => res.blob())
.then(blob => console.log(blob))

Denken Sie nicht, dass Sie es kleiner machen könnten, ohne libs zu verwenden

Endlos
quelle
Sehr elegant. Leider unterstützen Edge 13 und Safari "Fetch" nicht.
Alex_1948511
1
Es wird in Edge 14 und Safari 10.1
Endless
17
Asynchrone Version:const blob = await (await fetch(url)).blob();
Christian d'Heureuse
Funktioniert hervorragend, aber die Datei hat beim Lesen vom Server keine Erweiterung. Irgendwelche Gedanken?
Pauljeba
Der Server hat keine Blobs? node-fetchDosis haben jedoch ein Konzept von Blob, aber da es serverseitig ist, ist es ziemlich nutzlos. Außerdem haben Blobs keine Erweiterungen oder Dateinamen (es ist nur ein Container zum Speichern von Daten)
Endless
18
dataURItoBlob : function(dataURI, dataTYPE) {
        var binary = atob(dataURI.split(',')[1]), array = [];
        for(var i = 0; i < binary.length; i++) array.push(binary.charCodeAt(i));
        return new Blob([new Uint8Array(array)], {type: dataTYPE});
    }

input dataURI ist die Daten-URL und dataTYPE ist der Dateityp und gibt dann das Blob-Objekt aus

Shawn Wu
quelle
Das dataTYPEist eingebettet in dataURIund sollte daher wie in der ersten Antwort analysiert werden.
Noel Abrahams
dataURL2Blob stammt von meinem Plugin für den Bildprozess. Sie können diesen Link überprüfen. Ich kopiere einfach meinen eigenen Code. github.com/xenophon566/html5.upload/blob/master/js/…
Shawn Wu
12

XHR-basierte Methode.

function dataURLtoBlob( dataUrl, callback )
{
    var req = new XMLHttpRequest;

    req.open( 'GET', dataUrl );
    req.responseType = 'arraybuffer'; // Can't use blob directly because of https://crbug.com/412752

    req.onload = function fileLoaded(e)
    {
        // If you require the blob to have correct mime type
        var mime = this.getResponseHeader('content-type');

        callback( new Blob([this.response], {type:mime}) );
    };

    req.send();
}

dataURLtoBlob( 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==', function( blob )
{
    console.log( blob );
});
Adria
quelle
Scheint, das ist jetzt der beste Weg. Danke dir!
dizel3d
Funktioniert nicht in Safari - es wird ein Cross-Origin-Fehler ausgegeben, wenn die Seite von HTTPS geladen wird.
Martin Ždila
Die Frage ist Blob von DataURL?
Michal
3

Versuchen:

function dataURItoBlob(dataURI) {
    if(typeof dataURI !== 'string'){
        throw new Error('Invalid argument: dataURI must be a string');
    }
    dataURI = dataURI.split(',');
    var type = dataURI[0].split(':')[1].split(';')[0],
        byteString = atob(dataURI[1]),
        byteStringLength = byteString.length,
        arrayBuffer = new ArrayBuffer(byteStringLength),
        intArray = new Uint8Array(arrayBuffer);
    for (var i = 0; i < byteStringLength; i++) {
        intArray[i] = byteString.charCodeAt(i);
    }
    return new Blob([intArray], {
        type: type
    });
}
HaNdTriX
quelle
3

In modernen Browsern kann man den von Christian d'Heureuse vorgeschlagenen Liner in einem Kommentar verwenden:

const blob = await (await fetch(dataURI)).blob(); 
Jan Derk
quelle
2

Erstellen Sie einen Blob mit der XHR-API :

function dataURLtoBlob( dataUrl, callback )
{
    var req = new XMLHttpRequest;

    req.open( 'GET', dataUrl );
    req.responseType = 'blob';

    req.onload = function fileLoaded(e)
    {
        callback(this.response);
    };

    req.send();
}

var dataURI = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='

dataURLtoBlob(dataURI , function( blob )
{
    console.log( blob );
});

georgeawg
quelle
0

Verwenden Sie meinen Code, um dataURI in Blob umzuwandeln. Es ist einfacher und sauberer als andere.

function dataURItoBlob(dataURI) {
    var arr = dataURI.split(','), mime = arr[0].match(/:(.*?);/)[1];
    return new Blob([atob(arr[1])], {type:mime});
}
cuixiping
quelle
Können Sie erklären, warum Ihr Code nicht in ein int-Array konvertiert werden muss, während alle anderen dies tun?
Ameen
Siehe Blob () Konstruktor auf MDN
Cuixiping
@Rikard was meinst du? es hat keinen Einfluss auf das Bild
Cuixiping
2
Dies funktioniert nur für einige grundlegende Dinge. Sie müssten + decodeURIComponent entkommen es zuerst die meisten Content-Encoding unterstützt dies lesen . Aus diesem Grund konvertieren andere einen String in ein int-Array, um den langsamen / hungrigen Funktionsaufruf decodeURIComponent / atob zu vermeiden, und konvertieren direkt in die Bytes
Endless
0

Da keine dieser Antworten base64- und non-base64-dataURLs unterstützt, basiert diese auf der gelöschten Antwort von vuamitom:

// from /programming/37135417/download-canvas-as-png-in-fabric-js-giving-network-error/
var dataURLtoBlob = exports.dataURLtoBlob = function(dataurl) {
    var parts = dataurl.split(','), mime = parts[0].match(/:(.*?);/)[1]
    if(parts[0].indexOf('base64') !== -1) {
        var bstr = atob(parts[1]), n = bstr.length, u8arr = new Uint8Array(n)
        while(n--){
            u8arr[n] = bstr.charCodeAt(n)
        }

        return new Blob([u8arr], {type:mime})
    } else {
        var raw = decodeURIComponent(parts[1])
        return new Blob([raw], {type: mime})
    }
}

Hinweis: Ich bin mir nicht sicher, ob es solche gibt andere dataURL-MIME-Typen gibt, die möglicherweise anders behandelt werden müssen. Aber bitte lassen Sie es mich wissen, wenn Sie es herausfinden! Es ist möglich, dass dataURLs einfach ein beliebiges Format haben können. In diesem Fall liegt es an Ihnen, den richtigen Code für Ihren speziellen Anwendungsfall zu finden.

BT
quelle
-2

verwenden

FileReader.readAsArrayBuffer(Blob|File)

eher, als

FileReader.readAsDataURL(Blob|File)
3on
quelle
2
Ich muss es auf unbestimmte Zeit als dataURL in localStorage speichern, damit die Verwendung des alternativen ArrayBufferPfads nicht funktioniert.
Shane Holloway