ChatGPT解决这个技术问题 Extra ChatGPT

在 JavaScript 中从 Base64 字符串创建 BLOB

我在字符串中有 Base64 编码的二进制数据:

const contentType = 'image/png';
const b64Data = 'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==';

我想创建一个包含此数据的 blob: URL 并将其显示给用户:

const blob = new Blob(????, {type: contentType});
const blobUrl = URL.createObjectURL(blob);

window.location = blobUrl;

我一直无法弄清楚如何创建 BLOB。

在某些情况下,我可以通过使用 data: URL 来避免这种情况:

const dataUrl = `data:${contentType};base64,${b64Data}`;

window.location = dataUrl;

但是,在大多数情况下,data: URL 非常大。

如何在 JavaScript 中将 Base64 字符串解码为 BLOB 对象?


P
Peter Mortensen

atob 函数会将 Base64 编码的字符串解码为一个新字符串,其中二进制数据的每个字节都有一个字符。

const byteCharacters = atob(b64Data);

每个字符的代码点 (charCode) 将是字节的值。我们可以通过使用 .charCodeAt 方法为字符串中的每个字符应用它来创建一个字节值数组。

const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
    byteNumbers[i] = byteCharacters.charCodeAt(i);
}

您可以将此字节值数组转换为实际类型化的字节数组,方法是将其传递给 Uint8Array 构造函数。

const byteArray = new Uint8Array(byteNumbers);

反过来,可以通过将其包装在数组中并将其传递给 Blob 构造函数来将其转换为 BLOB。

const blob = new Blob([byteArray], {type: contentType});

上面的代码有效。但是,通过将 byteCharacters 处理成更小的切片而不是一次性处理,可以稍微提高性能。在我的粗略测试中,512 字节似乎是一个很好的切片大小。这为我们提供了以下功能。

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;

完整示例:

const b64toBlob = (b64Data, contentType='', sliceSize=512) => { const byteCharacters = atob(b64Data);常量字节数组 = []; 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});返回斑点; } 常量 contentType = '图片/png'; const b64Data = 'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==';常量 blob = b64toBlob(b64Data, contentType);常量 blobUrl = URL.createObjectURL(blob); const img = document.createElement('img'); img.src = blobUrl; document.body.appendChild(img);


嗨杰里米。我们的 Web 应用程序中有此代码,在下载的文件更大之前它不会导致任何问题。因此,当用户使用 Chrome 或 IE 下载大于 100mb 的文件时,它会导致生产服务器挂起和崩溃。我们发现 IE 中的以下行正在引发内存异常“var byteNumbers = new Array(slice.length)”。但是在 chrome 中,是 for 循环导致了同样的问题。我们找不到合适的解决方案来解决这个问题,然后我们转而使用 window.open 直接下载文件。你能在这里提供一些帮助吗?
这对我在 Chrome 和 Firefox 上的一些 blob 不起作用,但在边缘工作:/
这对我来说适用于图像,但不适用于 mp4 视频。有谁知道如何将视频 base64 字符串转换为 blob?任何帮助表示赞赏!
E
Endless

这是一个更简单的方法,没有任何依赖项或库。
它需要新的 fetch API。 (Can I use it?)

var url = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" fetch(url) .then(res => res.blob()) .then(console.log)

使用此方法,您还可以轻松获取 ReadableStream、ArrayBuffer、文本和 JSON。
(仅供参考,这也适用于 Node 中的 node-fetch

作为一个函数:

const b64toBlob = (base64, type = 'application/octet-stream') => 
  fetch(`data:${type};base64,${base64}`).then(res => res.blob())

我对 Jeremy 的 ES6 同步版本做了一个简单的性能测试。同步版本会阻止 UI 一段时间。保持开发工具打开会降低获取性能

document.body.innerHTML += '' // 得到一些虚拟渐变图像 var img=function(){var a=document.createElement("canvas"),b=a.getContext ("2d"),c=b.createLinearGradient(0,0,1500,1500);a.width=a.height=3000;c.addColorStop(0,"red");c.addColorStop(1,"blue ");b.fillStyle=c;b.fillRect(0,0,a.width,a.height);return a.toDataURL()}(); async function perf() { const blob = await fetch(img).then(res => res.blob()) // 将其转换为 dataURI const url = img const b64Data = url.split(',')[1 ] // Jeremy Banks 解决方案 const b64toBlob = (b64Data, contentType = '', sliceSize=512) => { const byteCharacters = atob(b64Data);常量字节数组 = []; 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});返回斑点; } // bench 阻塞方法 let i = 500 console.time('blocking b64') while (i--) { await b64toBlob(b64Data) } console.timeEnd('blocking b64') // bench 非阻塞 i = 500 / / 这样每次函数都不会重构 const toBlob = res => res.blob() console.time('fetch') while (i--) { await fetch(url).then(toBlob) } console.timeEnd ('fetch') console.log('done') } perf()


如果 base64 编码字符串的大小很大,比如说大于 665536 个字符,这仍然有效,这是 Opera 中 URI 大小的限制?
不知道,我知道这可能是对地址栏的限制,但是使用 AJAX 做事可能是一个例外,因为它不必被渲染。你必须测试它。如果它在我那里,我一开始就不会得到base64字符串。认为这是一种不好的做法,会占用更多的内存和时间来解码和编码。例如,createObjectURL 而不是 readAsDataURL 要好得多。如果您使用 ajax 上传文件,请选择 FormData 而不是 JSON,或者使用 canvas.toBlob 而不是 toDataURL
内联更好:await (await fetch(imageDataURL)).blob()
当然,如果您针对最新的浏览器。但这也要求该函数位于异步函数内部。说到... await fetch(url).then(r=>r.blob()) 是排序器
非常简洁的解决方案,但据我所知,由于 Access is denied. 错误,它不适用于 IE(使用 polyfill ofc)。我猜 fetch 在 blob url 下公开 blob - 与 URL.createObjectUrl 一样 - 这在 ie11 上不起作用。 reference。也许有一些解决方法可以将 fetch 与 IE11 一起使用?它看起来比其他同步解决方案好得多:)
B
Bacher

优化(但可读性较差)的实现:

function base64toBlob(base64Data, contentType) {
    contentType = contentType || '';
    var sliceSize = 1024;
    var byteCharacters = atob(base64Data);
    var bytesLength = byteCharacters.length;
    var slicesCount = Math.ceil(bytesLength / sliceSize);
    var byteArrays = new Array(slicesCount);

    for (var sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
        var begin = sliceIndex * sliceSize;
        var end = Math.min(begin + sliceSize, bytesLength);

        var bytes = new Array(end - begin);
        for (var offset = begin, i = 0; offset < end; ++i, ++offset) {
            bytes[i] = byteCharacters[offset].charCodeAt(0);
        }
        byteArrays[sliceIndex] = new Uint8Array(bytes);
    }
    return new Blob(byteArrays, { type: contentType });
}

是否有任何理由将字节切片成 blob?如果我不使用,是否有任何不利或风险?
在带有 Ionic 1 / Angular 1 的 Android 上运行良好。需要切片,否则我会遇到 OOM(Android 6.0.1)。
只有一个例子,我可以在 IE 11 和 Chrome 的企业环境中无缝处理任何文档类型。
一个解释将是有序的。例如,为什么它有更高的性能?
@PeterMortensen 那是几年前的事了,现在您可以尝试执行几种变体。想法是在重组周期条件检查和局部变量。
M
Mario Petrovic

以下是我的 TypeScript 代码,可以轻松转换为 JavaScript,您可以使用

/**
 * Convert BASE64 to BLOB
 * @param base64Image Pass Base64 image data to convert into the BLOB
 */
private convertBase64ToBlob(base64Image: string) {
  // Split into two parts
  const parts = base64Image.split(';base64,');

  // Hold the content type
  const imageType = parts[0].split(':')[1];

  // Decode Base64 string
  const decodedData = window.atob(parts[1]);

  // Create UNIT8ARRAY of size same as row data length
  const uInt8Array = new Uint8Array(decodedData.length);

  // Insert all character code into uInt8Array
  for (let i = 0; i < decodedData.length; ++i) {
    uInt8Array[i] = decodedData.charCodeAt(i);
  }

  // Return BLOB image after conversion
  return new Blob([uInt8Array], { type: imageType });
}

虽然此代码段可能是解决方案,但 including an explanation 确实有助于提高帖子的质量。请记住,您正在为将来的读者回答问题,而这些人可能不知道您的代码建议的原因。
另外,你为什么对评论大喊大叫?
您的 Typescript code 代码只有一个 SINGLE 类型,该类型是 any。比如为什么还要打扰??
很有用。我需要一个同步方法来做到这一点。完美的。谢谢。
P
Peter Mortensen

对于所有浏览器支持,尤其是在 Android 上,也许您可以添加以下内容:

try{
    blob = new Blob(byteArrays, {type : contentType});
}
catch(e){
    // TypeError old Google Chrome and Firefox
    window.BlobBuilder = window.BlobBuilder ||
                         window.WebKitBlobBuilder ||
                         window.MozBlobBuilder ||
                         window.MSBlobBuilder;
    if(e.name == 'TypeError' && window.BlobBuilder){
        var bb = new BlobBuilder();
        bb.append(byteArrays);
        blob = bb.getBlob(contentType);
    }
    else if(e.name == "InvalidStateError"){
        // InvalidStateError (tested on FF13 WinXP)
        blob = new Blob(byteArrays, {type : contentType});
    }
    else{
        // We're screwed, blob constructor unsupported entirely
    }
}

谢谢,但是如果我没看错的话,你上面写的代码片段有两个问题:(1)最后一个 else-if 上的 catch() 中的代码与 try() 中的原始代码相同:“blob = new Blob(byteArrays, {type : contentType})" ...我不知道您为什么建议在原始异常之后重复相同的代码? ... (2) BlobBuilder.append() 不能接受字节数组,但可以接受 ArrayBuffer。因此,在使用此 API 之前,输入字节数组必须进一步转换为其 ArrayBuffer。参考:developer.mozilla.org/en-US/docs/Web/API/BlobBuilder
A
Alejandro Reyes

请参阅此示例:https://jsfiddle.net/pqhdce2L/

函数 b64toBlob(b64Data, contentType, sliceSize) { contentType = contentType || '';切片大小 = 切片大小 || 512; var byteCharacters = atob(b64Data); var byteArrays = []; for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) { var slice = byteCharacters.slice(offset, offset + sliceSize); var byteNumbers = new Array(slice.length); for (var i = 0; i < slice.length; i++) { byteNumbers[i] = slice.charCodeAt(i); } var byteArray = new Uint8Array(byteNumbers); byteArrays.push(byteArray); } var blob = new Blob(byteArrays, {type: contentType});返回斑点; } var contentType = '图片/png'; var b64Data = 你的 Base64 编码; var blob = b64toBlob(b64Data, contentType); var blobUrl = URL.createObjectURL(blob); var img = document.createElement('img'); img.src = blobUrl; document.body.appendChild(img);


一个解释将是有序的。
P
Peter Mortensen

对于所有像我一样的复制粘贴爱好者,这里有一个适用于 Chrome、Firefox 和 Edge 的熟下载功能:

window.saveFile = function (bytesBase64, mimeType, fileName) {
var fileUrl = "data:" + mimeType + ";base64," + bytesBase64;
fetch(fileUrl)
    .then(response => response.blob())
    .then(blob => {
        var link = window.document.createElement("a");
        link.href = window.URL.createObjectURL(blob, { type: mimeType });
        link.download = fileName;
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
    });
}

和野生动物园(至少在桌面上)
A
Amir Nissim

对于图像数据,我发现使用 canvas.toBlob(异步)更简单

function b64toBlob(b64, onsuccess, onerror) {
    var img = new Image();

    img.onerror = onerror;

    img.onload = function onload() {
        var canvas = document.createElement('canvas');
        canvas.width = img.width;
        canvas.height = img.height;

        var ctx = canvas.getContext('2d');
        ctx.drawImage(img, 0, 0, canvas.width, canvas.height);

        canvas.toBlob(onsuccess);
    };

    img.src = b64;
}

var base64Data = 'data:image/jpg;base64,/9j/4AAQSkZJRgABAQA...';
b64toBlob(base64Data,
    function(blob) {
        var url = window.URL.createObjectURL(blob);
        // do something with url
    }, function(error) {
        // handle error
    });

我猜您会因此丢失一些信息...例如元信息,就像将任何图像转换为png一样,因此结果不一样,这也仅适用于图像
我想您可以通过从 base64 字符串中提取图像类型 image/jpg 来改进它,然后将其作为第二个参数传递给 toBlob 函数,以便结果是相同的类型。除此之外,我认为这是完美的——它节省了 30% 的流量和服务器上的磁盘空间(与 base64 相比),即使使用透明 PNG 也能很好地工作。
该函数在图像大于 2MB 时崩溃......在 Android 中我得到了异常:android.os.TransactionTooLarge
P
Peter Mortensen

我正在发布一种更具声明性的同步 Base64 转换的方式。虽然 async fetch().blob() 非常简洁而且我非常喜欢这个解决方案,但它在 Internet Explorer 11(可能还有 Edge - 我还没有测试过)上不起作用,即使使用 polyfill - 看看我对 Endless' post 的评论了解更多详情。

const blobPdfFromBase64String = base64String => {
   const byteArray = Uint8Array.from(
     atob(base64String)
       .split('')
       .map(char => char.charCodeAt(0))
   );
  return new Blob([byteArray], { type: 'application/pdf' });
};

奖金

如果要打印它,可以执行以下操作:

const isIE11 = !!(window.navigator && window.navigator.msSaveOrOpenBlob); // Or however you want to check it
const printPDF = blob => {
   try {
     isIE11
       ? window.navigator.msSaveOrOpenBlob(blob, 'documents.pdf')
       : printJS(URL.createObjectURL(blob)); // http://printjs.crabbly.com/
   } catch (e) {
     throw PDFError;
   }
};

奖励 x 2 - 在 Internet Explorer 11 的新选项卡中打开 BLOB 文件

如果您能够在服务器上对 Base64 字符串进行一些预处理,您可以在某个 URL 下公开它并使用 printJS 中的链接 :)


可以通知您 Edge 可以工作,Edge 现在是基于铬的,因此它应该支持 chrome 可以做的大多数事情
g
gabriele.genta

如果您可以忍受向您的项目添加一个依赖项,那么很棒的 blob-util npm package 提供了一个方便的 base64StringToBlob 功能。添加到 package.json 后,您可以像这样使用它:

import { base64StringToBlob } from 'blob-util';

const contentType = 'image/png';
const b64Data = 'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==';

const blob = base64StringToBlob(b64Data, contentType);

// Do whatever you need with your blob...

这个答案对我在 2021 年使用 Angular 12 有效
P
Peter Mortensen

我注意到,在像 Jeremy 建议的那样对数据进行切片时,Internet Explorer 11 变得异常缓慢。 Chrome 确实如此,但 Internet Explorer 在将切片数据传递给 Blob-Constructor 时似乎存在问题。在我的机器上,传递 5 MB 的数据会导致 Internet Explorer 崩溃,并且内存消耗正在飙升。 Chrome 会立即创建 Blob。

运行此代码进行比较:

var byteArrays = [],
    megaBytes = 2,
    byteArray = new Uint8Array(megaBytes*1024*1024),
    block,
    blobSlowOnIE, blobFastOnIE,
    i;

for (i = 0; i < (megaBytes*1024); i++) {
    block = new Uint8Array(1024);
    byteArrays.push(block);
}

//debugger;

console.profile("No Slices");
blobSlowOnIE = new Blob(byteArrays, { type: 'text/plain'});
console.profileEnd();

console.profile("Slices");
blobFastOnIE = new Blob([byteArray], { type: 'text/plain'});
console.profileEnd();

所以我决定将 Jeremy 描述的两种方法都包含在一个函数中。这要归功于他。

function base64toBlob(base64Data, contentType, sliceSize) {

    var byteCharacters,
        byteArray,
        byteNumbers,
        blobData,
        blob;

    contentType = contentType || '';

    byteCharacters = atob(base64Data);

    // Get BLOB data sliced or not
    blobData = sliceSize ? getBlobDataSliced() : getBlobDataAtOnce();

    blob = new Blob(blobData, { type: contentType });

    return blob;


    /*
     * Get BLOB data in one slice.
     * => Fast in Internet Explorer on new Blob(...)
     */
    function getBlobDataAtOnce() {
        byteNumbers = new Array(byteCharacters.length);

        for (var i = 0; i < byteCharacters.length; i++) {
            byteNumbers[i] = byteCharacters.charCodeAt(i);
        }

        byteArray = new Uint8Array(byteNumbers);

        return [byteArray];
    }

    /*
     * Get BLOB data in multiple slices.
     * => Slow in Internet Explorer on new Blob(...)
     */
    function getBlobDataSliced() {

        var slice,
            byteArrays = [];

        for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
            slice = byteCharacters.slice(offset, offset + sliceSize);

            byteNumbers = new Array(slice.length);

            for (var i = 0; i < slice.length; i++) {
                byteNumbers[i] = slice.charCodeAt(i);
            }

            byteArray = new Uint8Array(byteNumbers);

            // Add slice
            byteArrays.push(byteArray);
        }

        return byteArrays;
    }
}

谢谢你把这个包括在内。随着最近对 IE11 的更新(在 5/2016 和 8/2016 之间),从数组生成 blob 开始占用大量内存。通过将单个 Uint8Array 发送到博客构造函数中,它几乎不使用 ram 并实际完成了该过程。
将测试样本中的切片大小从 1K 增加到 8..16K 会显着减少 IE 中的时间。在我的 PC 上,原始代码需要 5 到 8 秒,8K 块的代码只需要 356 毫秒,而 16K 块的代码需要 225 毫秒
P
Peter Mortensen

带有 fetch 的方法是最好的解决方案,但是如果有人需要使用不带 fetch 的方法,那么这里就是,因为前面提到的那些对我不起作用:

function makeblob(dataURL) {
    const BASE64_MARKER = ';base64,';
    const parts = dataURL.split(BASE64_MARKER);
    const contentType = parts[0].split(':')[1];
    const raw = window.atob(parts[1]);
    const rawLength = raw.length;
    const uInt8Array = new Uint8Array(rawLength);

    for (let i = 0; i < rawLength; ++i) {
        uInt8Array[i] = raw.charCodeAt(i);
    }

    return new Blob([uInt8Array], { type: contentType });
}

G
GuruKay

这将被证明是一个很短的解决方案。

const byteArray = new Buffer(base64String.replace(/^[\w\d;:\/]+base64\,/g, ''), 'base64');

base64String 是包含 base 64 字符串的字符串。

byteArray 是您需要的数组。

正则表达式替换是可选的,它只是用来处理前缀,就像在 dataurl 字符串的情况下一样。


这会创建一个 Node JS Buffer 对象而不是浏览器 blob: url。此外,没有理由在正则表达式上设置 /g 全局标志,您只匹配开头,最多一次。
P
Puerto AGP

两种不同的变体

function base64ToBlob(base64, contentType='image/png', chunkLength=512) {
    const byteCharsArray = Array.from(atob(base64.substr(base64.indexOf(',') + 1)));
    const chunksIterator = new Array(Math.ceil(byteCharsArray.length / chunkLength));
    const bytesArrays = [];

    for (let c = 0; c < chunksIterator.length; c++) {
        bytesArrays.push(new Uint8Array(byteCharsArray.slice(c * chunkLength, chunkLength * (c + 1)).map(s => s.charCodeAt(0))));
    }

    const blob = new Blob(bytesArrays, {type: contentType});
    
    return blob;
}

/* Not sure how it performs with big images */
async function base64ToBlobLight(base64) { return await fetch(base64).then(res => res.blob()); }

/* Test */
const base64Data = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAB+FBMVEUAAAA/mUPidDHiLi5Cn0XkNTPmeUrkdUg/m0Q0pEfcpSbwaVdKskg+lUP4zA/iLi3msSHkOjVAmETdJSjtYFE/lkPnRj3sWUs8kkLeqCVIq0fxvhXqUkbVmSjwa1n1yBLepyX1xxP0xRXqUkboST9KukpHpUbuvRrzrhF/ljbwaljuZFM4jELaoSdLtElJrUj1xxP6zwzfqSU4i0HYnydMtUlIqUfywxb60AxZqEXaoifgMCXptR9MtklHpEY2iUHWnSjvvRr70QujkC+pUC/90glMuEnlOjVMt0j70QriLS1LtEnnRj3qUUXfIidOjsxAhcZFo0bjNDH0xxNLr0dIrUdmntVTkMoyfL8jcLBRuErhJyrgKyb4zA/5zg3tYFBBmUTmQTnhMinruBzvvhnxwxZ/st+Ktt5zp9hqota2vtK6y9FemNBblc9HiMiTtMbFtsM6gcPV2r6dwroseLrMrbQrdLGdyKoobKbo3Zh+ynrgVllZulTsXE3rV0pIqUf42UVUo0JyjEHoS0HmsiHRGR/lmRz/1hjqnxjvpRWfwtOhusaz0LRGf7FEfbDVmqHXlJeW0pbXq5bec3fX0nTnzmuJuWvhoFFhm0FtrziBsjaAaDCYWC+uSi6jQS3FsSfLJiTirCOkuCG1KiG+wSC+GBvgyhTszQ64Z77KAAAARXRSTlMAIQRDLyUgCwsE6ebm5ubg2dLR0byXl4FDQzU1NDEuLSUgC+vr6urq6ubb29vb2tra2tG8vLu7u7uXl5eXgYGBgYGBLiUALabIAAABsElEQVQoz12S9VPjQBxHt8VaOA6HE+AOzv1wd7pJk5I2adpCC7RUcHd3d3fXf5PvLkxheD++z+yb7GSRlwD/+Hj/APQCZWxM5M+goF+RMbHK594v+tPoiN1uHxkt+xzt9+R9wnRTZZQpXQ0T5uP1IQxToyOAZiQu5HEpjeA4SWIoksRxNiGC1tRZJ4LNxgHgnU5nJZBDvuDdl8lzQRBsQ+s9PZt7s7Pz8wsL39/DkIfZ4xlB2Gqsq62ta9oxVlVrNZpihFRpGO9fzQw1ms0NDWZz07iGkJmIFH8xxkc3a/WWlubmFkv9AB2SEpDvKxbjidN2faseaNV3zoHXvv7wMODJdkOHAegweAfFPx4G67KluxzottCU9n8CUqXzcIQdXOytAHqXxomvykhEKN9EFutG22p//0rbNvHVxiJywa8yS2KDfV1dfbu31H8jF1RHiTKtWYeHxUvq3bn0pyjCRaiRU6aDO+gb3aEfEeVNsDgm8zzLy9egPa7Qt8TSJdwhjplk06HH43ZNJ3s91KKCHQ5x4sw1fRGYDZ0n1L4FKb9/BP5JLYxToheoFCVxz57PPS8UhhEpLBVeAAAAAElFTkSuQmCC';
        
const blob = base64ToBlob(base64Data);
const blobUrl = URL.createObjectURL(blob);
const img = document.createElement('img');

img.src = blobUrl;
document.body.appendChild(img);

/**********************/

/* Test */
(async () => {
    const blob = await base64ToBlobLight(base64Data);
    const blobUrl = URL.createObjectURL(blob);
    const img = document.createElement('img');

    img.src = blobUrl;
    document.body.appendChild(img);
})();