A atobfunção decodificará uma string codificada em Base64 em uma nova string com um caractere para cada byte dos dados binários.
const byteCharacters = atob(b64Data);
O ponto de código de cada caractere (charCode) será o valor do byte. Podemos criar uma matriz de valores de bytes, aplicando isso usando o .charCodeAtmétodo para cada caractere na string.
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
Você pode converter essa matriz de valores de bytes em uma matriz de bytes digitada real passando-a para o Uint8Arrayconstrutor.
const byteArray = new Uint8Array(byteNumbers);
Por sua vez, isso pode ser convertido em um BLOB envolvendo-o em uma matriz e passando-o para o Blobconstrutor.
const blob = new Blob([byteArray], {type: contentType});
O código acima funciona. No entanto, o desempenho pode ser melhorado um pouco ao processar as byteCharactersfatias menores, em vez de todas de uma vez. No meu teste aproximado, 512 bytes parecem ser um bom tamanho de fatia. Isso nos dá a seguinte função.
const b64toBlob = (b64Data, contentType='', sliceSize=512) => {
const byteCharacters = atob(b64Data);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
const slice = byteCharacters.slice(offset, offset + sliceSize);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, {type: contentType});
return blob;
}
const blob = b64toBlob(b64Data, contentType);
const blobUrl = URL.createObjectURL(blob);
window.location = blobUrl;
Exemplo completo:
const b64toBlob = (b64Data, contentType='', sliceSize=512) => {
const byteCharacters = atob(b64Data);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
const slice = byteCharacters.slice(offset, offset + sliceSize);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, {type: contentType});
return blob;
}
const contentType = 'image/png';
const b64Data = 'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==';
const blob = b64toBlob(b64Data, contentType);
const blobUrl = URL.createObjectURL(blob);
const img = document.createElement('img');
img.src = blobUrl;
document.body.appendChild(img);