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?

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;

}

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


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


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

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


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

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


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

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,


@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.


-2

usar

FileReader.readAsArrayBuffer(Blob|File)

ao invés de

FileReader.readAsDataURL(Blob|File)

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.