Skip to content

Instantly share code, notes, and snippets.

@DarrenSem
Created October 29, 2022 18:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DarrenSem/4565d192473d92e0abfd7a08319a0d2c to your computer and use it in GitHub Desktop.
Save DarrenSem/4565d192473d92e0abfd7a08319a0d2c to your computer and use it in GitHub Desktop.
blobFromDataUrl.js and binaryFromDataUrl_RESEARCH (multiple ways including fetch and Uint8Array.from)
/////// binaryFromDataUrl_RESEARCH (multiple ways including fetch and Uint8Array.from).js
// const blobFromDataUrl=(d,z)=>(z=d.match(/^data:(.*?)(?:;base64)?,(.*)/),new Blob([Uint8Array.from(atob(z[2]),a=>a.charCodeAt(0))],{type:z[1]||"octet-stream"}));
// async function binaryFromDataUrl_RESEARCH(src) { // blobOrArrayBufferOrTypedArray = await binaryFromDataUrl_RESEARCH(dataUrl);
const binaryFromDataUrl_RESEARCH = async src => { // blobOrArrayBufferOrTypedArray = await binaryFromDataUrl_RESEARCH(dataUrl);
// src = "data:[<media type>][;base64],<data>" via https://en.wikipedia.org/wiki/Data_URI_scheme#Syntax
// const base64String = src.slice(src.indexOf(",") + 1); // const base64String = src.split(",", 2)[1]
// const [protocol, base64String] = src.split(",", 2), type = protocol.split(":")[1].split(";base64")[0];
const [, type, base64String] = src.match(/^data:(.*?)(?:;base64)?,(.*)/); // cf. /^[\w\d;:\/]+base64\,/
console.log({ type, base64String });
// via https://stackoverflow.com/questions/16245767/creating-a-blob-from-a-base64-string-in-javascript/72599458#72599458
if ("xyzMETHOD 1" === "METHOD 1") {
return fetch(src).then(r => r.blob()); // no need for return await fetch(src).then(r => r.blob());
};
// via https://stackoverflow.com/questions/16245767/creating-a-blob-from-a-base64-string-in-javascript/73181046#73181046
if ("xyzMETHOD 2 as a reminder of non-promise syntax: await (await first(v)).second()" === "METHOD 2 as a reminder of non-promise syntax: await (await first(v)).second()") {
return await (await fetch(src)).blob();
};
// via https://stackoverflow.com/questions/16245767/creating-a-blob-from-a-base64-string-in-javascript/73181046#73181046
if ("xyzMETHOD 3" === "METHOD 3") {
const binaryString = window.atob(base64String); // window.atob(...), because atob(...) makes VSC show Node suggestion to use Buffer.from(str,'base64')
return Uint8Array.from(binaryString, c => c.charCodeAt(0));
};
// ^ no TYPE tho :( so it "works" [*] but returns the BYTE ARRAY only. [*] because Blob([TypedArray]) is fine, PLUS download creates new Blob([data])
// via https://www.isummation.com/blog/convert-arraybuffer-to-base64-string-and-vice-versa/
if ("xyzMETHOD 4" === "METHOD 4") {
const binaryString = window.atob(base64String); // window.atob(...), because atob(...) makes VSC show Node suggestion to use Buffer.from(str,'base64')
const L = binaryString.length;
const bytes = new Uint8Array(L); // loop = same as (but faster than?) Uint8Array.from(binaryString, c => c.charCodeAt(0));
for (let i = 0; i < L; i++) {
bytes[i] = binaryString.charCodeAt(i);
};
// confirmed by https://developer.mozilla.org/en-US/docs/Web/API/Blob/Blob#parameters -- Blob[bytes.buffer] works ( Blob[ArrayBuffer(byteCount)] ), BUT SO DOES Blob[bytes] ( Blob[Uint8Array(byteCount)] )
return new Blob([bytes.buffer], { type: type || "octet-stream" }); // ~ "application/octet-binary"
};
if ("xyzMETHOD 5a" === "METHOD 5a") {
const binaryString = window.atob(base64String);
const bytes = Uint8Array.from(binaryString, c => c.charCodeAt(0));
return new Blob([bytes], { type: type || "octet-stream" }); // ~ "application/octet-binary"
};
if ("xyzMETHOD 5b JUST A LITTLE LESS CLEAR aka A LITTLE TOO 'CLEVER'..." === "METHOD 5b JUST A LITTLE LESS CLEAR aka A LITTLE TOO 'CLEVER'...") {
const binaryString = window.atob(base64String);
const buff = new Uint8Array([...binaryString].map(c => c.charCodeAt(0)));
// ^ using ...spread syntax, but otherwise same idea as how 5c works: buff = Uint8Array.from(window.atob(base64String), c => c.charCodeAt(0));
return new Blob([buff], { type: type || "octet-stream" }); // ~ "application/octet-binary"
};
if ("xyzUSELESS method (as-is was FAIL due to wrong buffer length, but even 'fixed' it has unneeded extra 'link' step)" === "USELESS method (as-is was FAIL due to wrong buffer length, but even 'fixed' it has unneeded extra 'link' step)") {
const binaryString = window.atob(base64String);
const L = binaryString.length;
// const buff = new ArrayBuffer(base64String.length); // actually BUG (the FINAL OUTPUT is too large; ZERO-PADDED BUFFER)
const buff = new ArrayBuffer(binaryString.length); // BUG 'fixed' -- now correct .length -- but still calling this useless because extra "link" step is unnecessary (I thought this maybe was because initially Blob([data]) only allowed data to be ArrayBuffer? idk, and idk)
const bytes = new Uint8Array(buff);
for (let i = 0; i < L; i++) {
bytes[i] = binaryString.charCodeAt(i);
};
return new Blob([buff], { type: type || "octet-stream" }); // ~ "application/octet-binary"
};
if ("BEST METHOD '5c' AKA one-liner version of 5a, AKA same as '3' but ALSO includes the TYPE" === "BEST METHOD '5c' AKA one-liner version of 5a, AKA same as '3' but ALSO includes the TYPE") {
return new Blob([Uint8Array.from(window.atob(base64String), c => c.charCodeAt(0))], { type: type || "octet-stream" }); // ~ "application/octet-binary"
};
if ("xyzSTANDALONE VERSION '6' (OF BEST METHOD '5c')" === "STANDALONE VERSION '6' (OF BEST METHOD '5c')") {
// const blobFromDataUrl=(d,z)=>(z=d.match(/^data:(.*?)(?:;base64)?,(.*)/),new Blob([Uint8Array.from(atob(z[2]),a=>a.charCodeAt(0))],{type:z[1]||"octet-stream"}));
const blobFromDataUrl = (dataUrl, z) => (
z = dataUrl.match(/^data:(.*?)(?:;base64)?,(.*)/) // cf. /^[\w\d;:\/]+base64\,/)
, new Blob([
Uint8Array.from(
atob(z[2])
, c => c.charCodeAt(0)
)
], {
type: z[1] || "octet-stream"
})
); // ~ "application/octet-binary" // blob = blobFromDataUrl(dataUrl)
return blobFromDataUrl(src);
};
};
//// download(Image) will FAIL because would just be .toString()
//// aka BLOB is needed for *anything* other than text (obv.)
//// cf. https://stackoverflow.com/questions/28636294/how-to-decode-dataimage-pngbase64-to-a-real-image-using-javascript/28636532#28636532
console.clear();
const exampleDataUrlHashtagPng = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAALEoAACxKAXd6dE0AAAAZSURBVBhXY/h/ks/e4wycZABSyIg0+ZN8AOS0Jbd/VjEXAAAAAElFTkSuQmCC";
const blobOrArrayBufferOrTypedArray = await binaryFromDataUrl_RESEARCH(exampleDataUrlHashtagPng);
const isBlob = blobOrArrayBufferOrTypedArray instanceof Blob;
const newBlob = isBlob ? blobOrArrayBufferOrTypedArray
: new Blob([blobOrArrayBufferOrTypedArray], {
type: blobOrArrayBufferOrTypedArray.type || "image/png"
});
console.log({ blobOrArrayBufferOrTypedArray }, { isBlob }, { newBlob });
const blobUrl = URL.createObjectURL(newBlob);
console.log("blobUrl =", blobUrl);
window.open(blobUrl, "_blank");
Object.assign(new FileReader(), {
onload: event => {
const bytes = new Uint8Array(event.target.result);
console.log("String.fromCharCode(bytes) =", [...bytes].map(b => String.fromCharCode(b)).join(""));
console.log("bytes =", bytes);
}
}).readAsArrayBuffer(newBlob);
Object.assign(new FileReader(), {
onload: event => console.log("dataUrl =", event.target.result)
}).readAsDataURL(newBlob);
"<all done except for the 2 FileReader.onload events>";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment