¿Blob de DataURL?

92

Usando FileReader's readAsDataURL()puedo transformar datos arbitrarios en una URL de datos. ¿Hay alguna forma de volver a convertir una URL de datos en una Blobinstancia utilizando apis de navegador integradas?

Shane Holloway
fuente

Respuestas:

151

El usuario Matt propuso el siguiente código hace un año ( ¿Cómo convertir dataURL en un objeto de archivo en javascript? ) Que podría ayudarlo

EDITAR: Como informaron algunos comentaristas, BlobBuilder ha quedado obsoleto hace algún tiempo. Este es el código actualizado:

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
fuente
4
La división duplicada parece un poco derrochadora, dado que podría ser una cadena muy grande.
Jesse Crossen
2
¿Cuál es el papel de la variable "ia"? Se le asigna un valor pero nunca se usa para formar el blob. ¿Por qué?
Blaze
1
Blaze, Ward: ia es una vista del búfer. Entonces, cuando configura cada byte en ia, está escribiendo en el búfer. Sin el bucle sobre ia, el búfer estará completamente vacío.
Mat
1
¿Cómo encuentro la respuesta SO # 6850276?
BT
1
@BT: Supongo que se pretende stackoverflow.com/a/30407840/271577 (tenga en cuenta que la URL redirigida incluye "# 6850276").
Brett Zamir
50

Como el método @Adria pero con Fetch api y un [ caniuse? ]
No tiene que pensar en mimetype ya que el tipo de respuesta de blob simplemente funciona de inmediato

Advertencia: puede violar la Política de seguridad de contenido (CSP)
... si usa ese material

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

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

No creas que podrías hacerlo más pequeño que esto sin usar lib's

Interminable
fuente
1
Muy elegante. Lamentablemente, edge 13 y safari no admiten "fetch".
alex_1948511
2
Es compatible con edge 14 y safari 10.1
Endless
19
Versión asincrónica:const blob = await (await fetch(url)).blob();
Christian d'Heureuse
Funciona muy bien, pero el archivo no tiene extensión cuando se lee desde el servidor. ¿Alguna idea?
pauljeba
1
El mayor problema de esto fetches que obliga a tener una API asíncrona.
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 es Data URL y dataTYPE es el tipo de archivo y luego el objeto blob de salida

Shawn Wu
fuente
1
El dataTYPEestá incrustado en dataURIy por lo tanto deben ser analizados como en la primera respuesta.
Noel Abrahams
dataURL2Blob proviene de mi complemento para el proceso de imagen, puede consultar este enlace. Solo copio mi propio código. github.com/xenophon566/html5.upload/blob/master/js/…
Shawn Wu
12

Método basado en 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
fuente
Parece que esta es la mejor manera ahora. ¡Gracias!
dizel3d
No funcionará en Safari: arrojará un error de origen cruzado si la página se carga desde HTTPS.
Martin Ždila
¿La pregunta es Blob de DataURL?
Michal
6

En los navegadores modernos, se puede usar el delineador sugerido por Christian d'Heureuse en un comentario:

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

tratar:

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
fuente
2

Cree un blob con la 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
fuente
0

Use mi código para convertir dataURI en blob. Es más simple y más limpio que otros.

function dataURItoBlob(dataURI) {
    var arr = dataURI.split(','), mime = arr[0].match(/:(.*?);/)[1];
    return new Blob([atob(arr[1])], {type:mime});
}
cuixiping
fuente
¿Puede explicar por qué su código no necesita la conversión a una matriz int mientras todos los demás lo hacen?
Ameen
Ver el constructor Blob () en MDN
cuixiping
@Rikard ¿a qué te refieres? no afecta ninguna imagen
cuixiping
2
Esto solo funciona para algunas cosas básicas. Debería escapar + decodeURIComponent primero para admitir la mayoría de codificación de contenido, lea esto . Es por eso que otros convierten una cadena en una matriz int para evitar la llamada a la función decodeURIComponent / atob lenta / hambrienta y convertir directamente a los bytes
Endless
0

Dado que ninguna de estas respuestas admite dataURL base64 y no base64, aquí hay una que sí se basa en la respuesta eliminada 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})
    }
}

Nota: No estoy seguro de si hay otros tipos de mime de dataURL que podrían tener que manejarse de manera diferente. ¡Pero avíseme si se entera! Es posible que dataURL simplemente tenga cualquier formato que deseen, y en ese caso dependerá de usted encontrar el código correcto para su caso de uso particular.

BT
fuente
-2

utilizar

FileReader.readAsArrayBuffer(Blob|File)

más bien que

FileReader.readAsDataURL(Blob|File)
3 en
fuente
2
Tengo que almacenarlo como DataURL durante un período indefinido en localStorage, por lo que usar la ArrayBufferruta alternativa no funcionará.
Shane Holloway