Blob de DataURL?

92

En utilisant FileReader's, readAsDataURL()je peux transformer des données arbitraires en une URL de données. Existe-t-il un moyen de reconvertir une URL de données en une Blobinstance à l'aide des API de navigateur intégrées?

Shane Holloway
la source

Réponses:

151

L'utilisateur Matt a proposé le code suivant il y a un an ( Comment convertir dataURL en objet fichier en javascript? ) Qui pourrait vous aider

EDIT: Comme certains commentateurs l'ont signalé, BlobBuilder est obsolète il y a quelque temps. Voici le code mis à jour:

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
la source
4
Le partage dupliqué semble un peu inutile, étant donné qu'il pourrait s'agir d'une très grande chaîne.
Jesse Crossen
2
Quel est le rôle de la variable "ia" - une valeur lui est attribuée mais n'est jamais utilisée pour former le blob. Pourquoi?
Blaze
1
Blaze, Ward: ia est une vue du tampon. Ainsi, lorsque vous définissez chaque octet dans ia, il écrit dans le tampon. Sans la boucle sur ia, le tampon sera complètement vide.
Mat
1
Comment puis-je trouver la réponse SO 6850276?
BT
1
@BT: Je suppose que stackoverflow.com/a/30407840/271577 est destiné (notez que l'URL redirigée inclut "# 6850276").
Brett Zamir
50

Comme la méthode @Adria mais avec Fetch api et juste plus petit [ caniuse? ]
Pas besoin de penser au type MIME, car le type de réponse blob fonctionne immédiatement

Avertissement: peut violer la politique de sécurité du contenu (CSP)
... si vous utilisez ce genre de choses

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

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

Ne pensez pas que vous pourriez le faire plus petit que cela sans utiliser les lib

Interminable
la source
1
Très élégant. Malheureusement, edge 13 et safari ne supportent pas "fetch".
alex_1948511
2
Il est pris en charge dans edge 14 et safari 10.1
Endless
19
Version asynchrone:const blob = await (await fetch(url)).blob();
Christian d'Heureuse
Fonctionne très bien, mais le fichier n'a pas d'extension lorsqu'il est lu à partir du serveur. Des pensées?
pauljeba le
1
Le plus gros problème fetchest qu'il est forcé d'avoir une API asynchrone.
Dennis C
19
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 est l'URL de données et dataTYPE est le type de fichier, puis l'objet blob de sortie

Shawn Wu
la source
1
Le dataTYPEest intégré dataURIet doit donc être analysé comme dans la première réponse.
Noel Abrahams
dataURL2Blob est venu de mon plugin pour le processus d'image, vous pouvez consulter ce lien. Je copie juste mon propre code. github.com/xenophon566/html5.upload/blob/master/js/…
Shawn Wu
12

Méthode basée sur XHR.

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
la source
Semble, c'est la meilleure façon maintenant. Merci!
dizel3d
Ne fonctionnera pas dans Safari - cela générera une erreur d'origine croisée si la page est chargée à partir de HTTPS.
Martin Ždila
La question est Blob de DataURL?
Michal
6

Dans les navigateurs modernes, on peut utiliser le seul liner suggéré par Christian d'Heureuse dans un commentaire:

const blob = await (await fetch(dataURI)).blob(); 
Jan Derk
la source
3

essayer:

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
la source
2

Créez un objet blob à l'aide de l' API XHR :

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
la source
0

Utilisez mon code pour convertir dataURI en blob. C'est plus simple et plus propre que d'autres.

function dataURItoBlob(dataURI) {
    var arr = dataURI.split(','), mime = arr[0].match(/:(.*?);/)[1];
    return new Blob([atob(arr[1])], {type:mime});
}
cuixiping
la source
Pouvez-vous expliquer pourquoi votre code n'a pas besoin de la conversion en tableau int alors que tout le monde le fait?
Ameen
Voir le constructeur Blob () sur MDN
cuixiping
@Rikard que voulez-vous dire? cela n'affecte aucune image
cuixiping
2
Cela ne fonctionne que pour certains éléments de base. Vous devrez d'abord échapper + decodeURIComponent pour prendre en charge la plupart des encodages de contenu, lire ceci . C'est pourquoi d'autres convertissent une chaîne en tableau int pour éviter l'appel de la fonction decodeURIComponent / atob lent / affamé et la convertissent directement en octets
fin
0

Étant donné qu'aucune de ces réponses ne prend en charge les URL de données base64 et non base64, en voici une basée sur la réponse supprimée de 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})
    }
}

Remarque: je ne suis pas sûr s'il existe d' autres types mime dataURL qui pourraient devoir être traités différemment. Mais faites-le moi savoir si vous le découvrez! Il est possible que les dataURL puissent simplement avoir le format de leur choix, et dans ce cas, ce serait à vous de trouver le bon code pour votre cas d'utilisation particulier.

BT
la source
-2

utilisation

FileReader.readAsArrayBuffer(Blob|File)

plutôt que

FileReader.readAsDataURL(Blob|File)
3on
la source
2
Je dois le stocker en tant que DataURL pour une période indéfinie dans localStorage, donc utiliser le ArrayBufferchemin alternatif ne fonctionnera pas.
Shane Holloway