Blob de DataURL?

93

Usando FileReadero readAsDataURL(), posso transformar dados arbitrários em uma URL de dados. Existe uma maneira de converter um URL de dados de volta em uma Blobinstância usando apis do navegador embutido?

Shane Holloway
fonte

Respostas:

153

O usuário Matt propôs o seguinte código há um ano ( Como converter dataURL em objeto de arquivo em javascript? ) Que pode ajudá-lo

EDIT: Como alguns comentadores relataram, BlobBuilder foi preterido há algum tempo. Este é o código atualizado:

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
fonte
4
A divisão duplicada parece um desperdício, visto que pode ser uma string muito grande.
Jesse Crossen de
2
Qual é o papel da variável "ia" - é atribuído um valor, mas nunca é usado na formação do blob. Por quê?
Blaze
1
Blaze, Ward: ia é uma visão do buffer. Portanto, quando você configura cada byte em ia, ele é escrito no buffer. Sem o loop over ia, o buffer estará completamente vazio.
Mat
1
Como encontro a resposta SO # 6850276?
BT de
1
@BT: Acho que stackoverflow.com/a/30407840/271577 é o objetivo (observe que o URL redirecionado inclui "# 6850276").
Brett Zamir de
54

Como o método @Adria, mas com Fetch api e apenas menor [ caniuse? ]
Não é preciso pensar no tipo MIME, já que o tipo de resposta do blob funciona fora da caixa

Aviso: pode violar a Política de Segurança de Conteúdo (CSP)
... se você usar essas coisas

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

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

Não pense que você poderia fazer isso menor do que este sem usar lib's

Sem fim
fonte
1
Muito elegante. Infelizmente o edge 13 e o safari não suportam "fetch".
alex_1948511
2
É compatível com edge 14 e safari 10.1
Endless
21
Versão assíncrona:const blob = await (await fetch(url)).blob();
Christian d'Heureuse
Funciona muito bem, mas o arquivo não tem extensão quando lido do servidor. Alguma ideia?
pauljeba
1
O maior problema disso fetché a força de ter uma API assíncrona.
Dennis C
21
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 é o URL de dados e dataTYPE é o tipo de arquivo e o objeto blob de saída

Shawn Wu
fonte
1
O dataTYPEestá embutido dataURIe, portanto, deve ser analisado como na primeira resposta.
Noel Abrahams
dataURL2Blob veio do meu plugin para o processo de imagem, você pode verificar este link. Acabei de copiar meu próprio código. github.com/xenophon566/html5.upload/blob/master/js/…
Shawn Wu
12

Método baseado em 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
fonte
Parece que esta é a melhor maneira agora. Obrigado!
dizel3d
Não funcionará no Safari - gerará um erro de origem cruzada se a página for carregada de HTTPS.
Martin Ždila
A questão é Blob de DataURL?
Michal
8

Em navegadores modernos, pode-se usar o único liner sugerido por Christian d'Heureuse em um comentário:

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

experimentar:

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

Crie um blob usando a 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
fonte
0

Use meu código para converter dataURI em blob. É mais simples e mais limpo do que outros.

function dataURItoBlob(dataURI) {
    var arr = dataURI.split(','), mime = arr[0].match(/:(.*?);/)[1];
    return new Blob([atob(arr[1])], {type:mime});
}
cuixiping
fonte
Você pode explicar por que seu código não precisa da conversão para o array int enquanto todo mundo está fazendo isso?
Ameen,
Veja o construtor Blob () em MDN
cuixiping
@Rikard o que você quer dizer? não afeta nenhuma imagem
cuixiping em
2
Isso só funciona para algumas coisas básicas. Você precisaria escapar + decodeURIComponent-lo primeiro para suportar a maior parte da codificação de conteúdo ler isso . É por isso que outros convertem uma string em array int para evitar a chamada de função decodeURIComponent / atob lenta / faminta e convertem diretamente em bytes
Endless
0

Como nenhuma dessas respostas oferece suporte a dataURLs de base64 e não-base64, aqui está uma que o faz com base na resposta excluída 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})
    }
}

Observação: não tenho certeza se há outros tipos mime dataURL que podem ter que ser tratados de forma diferente. Mas, por favor, deixe-me saber se você descobrir! É possível que dataURLs possam simplesmente ter qualquer formato que desejem e, nesse caso, caberia a você encontrar o código certo para seu caso de uso específico.

BT
fonte
-2

usar

FileReader.readAsArrayBuffer(Blob|File)

ao invés de

FileReader.readAsDataURL(Blob|File)
3on
fonte
2
Tenho que armazená-lo como um DataURL por um período indefinido em localStorage, portanto, usar o ArrayBuffercaminho alternativo não funcionará.
Shane Holloway