Creating a BLOB from a Base64 string in JavaScript

后端 未结 12 2657
说谎
说谎 2020-11-21 04:24

I have Base64-encoded binary data in a string:

const contentType = \'image/png\';
const b64Data = \'iVBORw0KGg         


        
12条回答
  •  栀梦
    栀梦 (楼主)
    2020-11-21 05:06

    Here is a more minimal method without any dependencies or libraries.
    It requires the new fetch API. (Can I use it?)

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

    With this method you can also easily get a ReadableStream, ArrayBuffer, text, and JSON.
    (fyi this also works with node-fetch in Node)

    As a function:

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

    I did a simple performance test towards Jeremy's ES6 sync version.
    The sync version will block UI for a while. keeping the devtool open can slow the fetch performance

    document.body.innerHTML += ''
    // get some dummy gradient image
    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())
      // turn it to a dataURI
      const url = img
      const b64Data = url.split(',')[1]
    
      // Jeremy Banks solution
      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;
      }
    
      // bench blocking method
      let i = 500
      console.time('b64')
      while (i--) {
        await b64toBlob(b64Data)
      }
      console.timeEnd('b64')
      
      // bench non blocking
      i = 500
    
      // so that the function is not reconstructed each time
      const toBlob = res => res.blob()
      console.time('fetch')
      while (i--) {
        await fetch(url).then(toBlob)
      }
      console.timeEnd('fetch')
      console.log('done')
    }
    
    perf()

提交回复
热议问题