DataURL, Blob, and File are common front-end objects for storing binary data. They are used in different places and sometimes require conversions between the three

To DataURL

Blob ==> DataURL

The first and easiest way to parse a Blob object is to use FileReader:

const blob = new Blob([JSON.stringify({ hello: 'javascript' }, null.2)] and {type : 'application/json'});

const fr = new FileReader();
fr.onload = function (e) {
  console.log(e.target.result); // data:application/json; base64,ewogICJoZWxsbyI6ICJqYXZhc2NyaXB0Igp9
}
fr.readAsDataURL(blob)
Copy the code

Of course, you can also choose to convert the Blob toa string and then use BTOA to convert it toa Base64-encoded DataURL

Note that bTOA requires primitive string encoding to be Latin-1. Latin-1 is a single-byte encoding character set, that is, each character encoding cannot exceed 255, otherwise an error will be reported

const blob = new Blob([JSON.stringify({ hello: 'javascript' }, null.2)] and {type : 'application/json'});

async function readAsDataURL(blob) {
  const str = await blob.text();
  const dataURL = 'data:' + blob.type + '; base64,' + btoa(str);
  return dataURL;
}

readAsDataURL(blob).then(dataurl= > {
  console.log(dataurl); // data:application/json; base64,ewogICJoZWxsbyI6ICJqYXZhc2NyaXB0Igp9
})
Copy the code

ArrayBuffer ==> DataURL

Similar to the Blob conversion to DataURL above, an ArrayBuffer can be converted to DataURL via BTOA

const arrBuf = await fetch('test.png').then(res= > res.arrayBuffer()); // Assume the data arrBuf is an ArrayBuffer

function readAsDataURL(arraybuffer, type) {
    let str = ' ';
    new Uint8Array(arraybuffer).forEach(code= > {
        str += String.fromCodePoint(code);
    });
    return 'data:' + type + '; base64,' + btoa(str);
}

const dataURL = readAsDataURL(arrBuf,  'image/png');
Copy the code

Image ==> DataURL

If you want to convert images, there is another way to convert them indirectly via canvas:

One thing to note is that img needs to explicitly add img.crossOrigin = ‘Anonymous’, otherwise when canvas executes toDataURL(), toBlob(), getImageData(), it will throw an error due to cross-domain security:

Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.

function imageToDataURL(imgurl) {
    return new Promise((resolve, reject) = > {
        const canvas = document.createElement('canvas');
        const img = new Image();
        img.src = imgurl;
        img.crossOrigin = 'Anonymous';
        img.onload = function() {
            canvas.width = img.naturalWidth * window.devicePixelRatio;
            canvas.height = img.naturalHeight * window.devicePixelRatio;
            const ctx = canvas.getContext('2d');
            ctx.drawImage(img, 0.0, canvas.width, canvas.height);
            const dataURL = canvas.toDataURL();
            resolve(dataURL);
        }
        img.onerror = reject;
    });
}

const dataURL = await imageToDataURL('http://test.com/image.png');
Copy the code

Into a Blob

DataURL ==> Blob

If your dataURL contains image data, you can also relay it via Canvas

function dataURLToBlob(dataurl) {
    return new Promise((resolve, reject) = > {
        const canvas = document.createElement('canvas');
        const img = new Image();
        img.src = dataurl;
        img.crossOrigin = 'Anonymous';
        img.onload = function() {
            canvas.width = img.naturalWidth * window.devicePixelRatio;
            canvas.height = img.naturalHeight * window.devicePixelRatio;
            const ctx = canvas.getContext('2d');
            ctx.drawImage(img, 0.0, canvas.width, canvas.height);
            canvas.toBlob(blob= > resolve(blob));
        }
        img.onerror = reject;
    });
}

const blob = dataURLToBlob('data:image/png; base64,xxxxxxx');
Copy the code

The second method is to convert through the ATOB function

function dataURLToBlob(dataurl) {
  const type = dataurl.match(/data:(.+); /) [1];
  const base64 = dataurl.split(', ') [1];
  const binStr = atob(base64);
  const u8a = new Uint8Array(binStr.length);
  let p = binStr.length;
  while (p) {
    p--;
    u8a[p] = binStr.codePointAt(p);
  }
  return new Blob([u8a], { type });
}
ArrayBuffer==> Blob Blob objects can be built directly using arrayBufferconst blob = new Blob([arrayBuffer], { type: 'image/png' });
Copy the code

To ArrayBuffer

DataURL ==> ArrayBuffer

Just make a few changes to the way dataURL goes to BLOB

function dataURLToBlob(dataurl) {
  const type = dataurl.match(/data:(.+); /) [1];
  const base64 = dataurl.split(', ') [1];
  const binStr = atob(base64);
  const u8a = new Uint8Array(binStr.length);
  let p = binStr.length;
  while (p) {
    p--;
    u8a[p] = binStr.codePointAt(p);
  }
  return u8a.buffer;
}
Copy the code

Blob ==> ArrayBuffer

Blob objects have an arrayBuffer() method that can be converted directly. Note that this method returns a Promise object, and the value after resolve is an arrayBuffer

const blob = new Blob([1.2.3.4]);
const arrBuf = await blob.arrayBuffer();
Copy the code