Created
October 29, 2022 18:49
-
-
Save DarrenSem/4565d192473d92e0abfd7a08319a0d2c to your computer and use it in GitHub Desktop.
blobFromDataUrl.js and binaryFromDataUrl_RESEARCH (multiple ways including fetch and Uint8Array.from)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/////// 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