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?

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;

}

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


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


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 );
});

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


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
    });
}

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 );
});


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});
}

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.


-2

utilisation

FileReader.readAsArrayBuffer(Blob|File)

plutôt que

FileReader.readAsDataURL(Blob|File)

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.