A atob
funçã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 .charCodeAt
mé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 Uint8Array
construtor.
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 Blob
construtor.
const blob = new Blob([byteArray], {type: contentType});
O código acima funciona. No entanto, o desempenho pode ser melhorado um pouco ao processar as byteCharacters
fatias 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);