I have a JPG that I import in Vite like import data from "whatever.jpg?raw";
. My goal is to encode the resulting raw JPEG string as a data URI like data:image/jpeg;base64,DATA
. The JPEG is very small (20x13, 1 KB), so size shouldn't be an issue. The problem is that I can't figure out how to get the correct output.
My idea for what the "correct" output should look like es from running the JPEG through , and I've been able to verify that my browser correctly renders that output. Here it is:
data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QCMRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAABIAAAAAQAAAEgAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAABSgAwAEAAAAAQAAAA0AAAAA/+0AOFBob3Rvc2hvcCAzLjAAOEJJTQQEAAAAAAAAOEJJTQQlAAAAAAAQ1B2M2Y8AsgTpgAmY7PhCfv/AABEIAA0AFAMBIgACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/3QAEAAL/2gAMAwEAAhEDEQA/APTvil+2F4gb4MMll4P1Pwhq93DbmbVo7yC6hti0oVhGEYSEHkCRlQAHccCsz9j347eFPC4vZLHWm1GHVnQawlwI4kbUVCotxHKSTmQYVw7lF2ptwxbd4JoXj7VPFMGp6dqd7fXEWqCOK/zdE/akC7VV9wPAUBcAgY7Vuz+CfD2i2uoQ2+kxzR3qi3uUu5HmSVScnKk47nIAwa+Jnm3J8bbn00Vunm/608zopzUIuDimn959geKP2v7TStauLSL4V+N79YjtM8UNsqsR1xmX9ayv+G0IP+iP+O/+/dp/8dr4813WdV+2hU1zWI40QKkaalMAijgADd0rO/tfV/8AoP61/wCDOf8A+Kq1mlR/b/8AJf8A7Y42tdF/X3H/2Q==
I've also found that I can get that output back to the original string with this one-liner:
await (await (await fetch(output)).blob()).text();
So I've got an output "target" that I know I should be getting, and you have a way to see the original string. So let me explain what I've tried that isn't working.
btoa()
My project is an SSR project which will run on Cloudflare Workers, so I need to be careful that any functions I use are isomorphic.
Since this function is marked as (deprecated) in Node.js, I'd rather find another way to do this, but I tried it anyways. After running btoa(data)
I got this error:
Uncaught DOMException: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.
at <anonymous>:1:1
After some searching, I read that the solution is to instead do btoa(unescape(encodeURIComponent(data)))
:
77+977+977+977+9ABBKRklGAAEBAABIAEgAAO+/ve+/vQDvv71FeGlmAABNTQAqAAAACAAFARIAAwAAAAEAAQAAARoABQAAAAEAAABKARsABQAAAAEAAABSASgAAwAAAAEAAgAA77+9aQAEAAAAAQAAAFoAAAAAAAAASAAAAAEAAABIAAAAAQAD77+9AQADAAAAAQABAADvv70CAAQAAAABAAAAFO+/vQMABAAAAAEAAAANAAAAAO+/ve+/vQA4UGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAAA4QklNBCUAAAAAABDvv70d77+92Y8A77+9BO+/vQnvv73vv73vv71Cfu+/ve+/vQARCAANABQDASIAAhEBAxEB77+977+9AB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC++/ve+/vQDvv70QAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQy77+977+977+9CCNC77+977+9FVLvv73vv70kM2Jy77+9CQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eu+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/vQAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgvvv73vv70A77+9EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIy77+9CBRC77+977+977+977+9CSMzUu+/vRVicu+/vQoWJDTvv70l77+9FxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXrvv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv70AQwADAgIDAgIDAwMDBAMDBAUIBQUEBAUKBwcGCAwKDAwLCgsLDQ4SEA0OEQ4LCxAWEBETFBUVFQwPFxgWFBgSFBUU77+977+9AEMBAwQEBQQFCQUFCRQNCw0UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFO+/ve+/vQAEAALvv73vv70ADAMBAAIRAxEAPwDvv73vv71f77+9F++/vRvvv73vv70l77+977+977+9Pwhq77+9cNuZ77+9aO+/vSDvv73vv73YtO+/vVhGEe+/ve+/vR5A77+977+9AAdx77+977+977+977+977+947eFPC4vZO+/vdabUe+/vVZ0Gu+/vVwI77+9Ru+/vVQqLe+/vXLvv71OZBhXDu+/vRdqbe+/vRbvv73vv73vv70X77+977+9TxTvv73vv73vv73ane+/ve+/ve+/vVrvv73vv70r77+977+9E++/ve+/vQvvv71V77+9A++/vVAXAO+/ve+/vdW7P++/vXw977+977+977+9EO+/ve+/vTHvv70d77+9e++/ve+/ve+/ve+/vUlU77+977+977+9OO+/vXIA77+977+977+977+9be+/ve+/ve+/ve+/vUVu77+9b++/ve+/ve+/ve+/vTUI77+9OO+/ve+/ve+/vX3vv73vv73vv73vv73vv71K1q4tIu+/vVfvv71777+977+977+9M++/vQ3vv73vv70R77+9Ge+/ve+/ve+/ve+/ve+/vW0IP++/ve+/ve+/ve+/ve+/ve+/vX/vv73vv73vv73vv71d77+9dV/vv73vv71Nc1jvv700QO+/vRpqUwDvv704AA3vv70rO++/vV9X77+9AO+/ve+/ve+/ve+/vQDvv70577+9AO+/ve+/ve+/ve+/vVR/b++/vQAl77+9AO+/vTbvv73vv71/X3Hvv73vv70=
However, as you can see, the output is wrong. I'm expecting some string like /9j/4AAQSk...F/X3H/2Q==
based on the "correct" output above, but this string is like 77+977+977...Hvv73vv70=
. Not at all the same.
js-base64
Let's try using a library. Here's what I tried:
import { toBase64 } from "js-base64";
toBase64(data);
However, I get the same incorrect output above. The library does have a urlsafe
argument, though, so I tried that too:
toBase64(data, true);
But that doesn't get me the right output either. I end up with this:
77-977-977-977-9ABBKRklGAAEBAABIAEgAAO-_ve-_vQDvv71FeGlmAABNTQAqAAAACAAFARIAAwAAAAEAAQAAARoABQAAAAEAAABKARsABQAAAAEAAABSASgAAwAAAAEAAgAA77-9aQAEAAAAAQAAAFoAAAAAAAAASAAAAAEAAABIAAAAAQAD77-9AQADAAAAAQABAADvv70CAAQAAAABAAAAFO-_vQMABAAAAAEAAAANAAAAAO-_ve-_vQA4UGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAAA4QklNBCUAAAAAABDvv70d77-92Y8A77-9BO-_vQnvv73vv73vv71Cfu-_ve-_vQARCAANABQDASIAAhEBAxEB77-977-9AB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC--_ve-_vQDvv70QAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQy77-977-977-9CCNC77-977-9FVLvv73vv70kM2Jy77-9CQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eu-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_vQAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgvvv73vv70A77-9EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIy77-9CBRC77-977-977-977-9CSMzUu-_vRVicu-_vQoWJDTvv70l77-9FxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXrvv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv70AQwADAgIDAgIDAwMDBAMDBAUIBQUEBAUKBwcGCAwKDAwLCgsLDQ4SEA0OEQ4LCxAWEBETFBUVFQwPFxgWFBgSFBUU77-977-9AEMBAwQEBQQFCQUFCRQNCw0UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFO-_ve-_vQAEAALvv73vv70ADAMBAAIRAxEAPwDvv73vv71f77-9F--_vRvvv73vv70l77-977-977-9Pwhq77-9cNuZ77-9aO-_vSDvv73vv73YtO-_vVhGEe-_ve-_vR5A77-977-9AAdx77-977-977-977-977-947eFPC4vZO-_vdabUe-_vVZ0Gu-_vVwI77-9Ru-_vVQqLe-_vXLvv71OZBhXDu-_vRdqbe-_vRbvv73vv73vv70X77-977-9TxTvv73vv73vv73ane-_ve-_ve-_vVrvv73vv70r77-977-9E--_ve-_vQvvv71V77-9A--_vVAXAO-_ve-_vdW7P--_vXw977-977-977-9EO-_ve-_vTHvv70d77-9e--_ve-_ve-_ve-_vUlU77-977-977-9OO-_vXIA77-977-977-977-9be-_ve-_ve-_ve-_vUVu77-9b--_ve-_ve-_ve-_vTUI77-9OO-_ve-_ve-_vX3vv73vv73vv73vv73vv71K1q4tIu-_vVfvv71777-977-977-9M--_vQ3vv73vv70R77-9Ge-_ve-_ve-_ve-_ve-_vW0IP--_ve-_ve-_ve-_ve-_ve-_vX_vv73vv73vv73vv71d77-9dV_vv73vv71Nc1jvv700QO-_vRpqUwDvv704AA3vv70rO--_vV9X77-9AO-_ve-_ve-_ve-_vQDvv70577-9AO-_ve-_ve-_ve-_vVR_b--_vQAl77-9AO-_vTbvv73vv71_X3Hvv73vv70
Buffer.from(data).toString("base64")
Even though this is a Node.js API and doesn't work in my browser, I gave it a try wrapping it in if (import.meta.env.SSR)
, but I get the same 77+977+977...Hvv73vv70=
output from above.
So what am I missing here? How do I get the correct Base64 output? I tried taking the "incorrect" output I got and correctly prefixing it with data:image/jpeg;base64,
, but not surprisingly the browser doesn't render it. What do I need to do to get the same "correct" output which I got when running the image through ?
I have a JPG that I import in Vite like import data from "whatever.jpg?raw";
. My goal is to encode the resulting raw JPEG string as a data URI like data:image/jpeg;base64,DATA
. The JPEG is very small (20x13, 1 KB), so size shouldn't be an issue. The problem is that I can't figure out how to get the correct output.
My idea for what the "correct" output should look like es from running the JPEG through https://www.base64-image.de, and I've been able to verify that my browser correctly renders that output. Here it is:
data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QCMRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAABIAAAAAQAAAEgAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAABSgAwAEAAAAAQAAAA0AAAAA/+0AOFBob3Rvc2hvcCAzLjAAOEJJTQQEAAAAAAAAOEJJTQQlAAAAAAAQ1B2M2Y8AsgTpgAmY7PhCfv/AABEIAA0AFAMBIgACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/3QAEAAL/2gAMAwEAAhEDEQA/APTvil+2F4gb4MMll4P1Pwhq93DbmbVo7yC6hti0oVhGEYSEHkCRlQAHccCsz9j347eFPC4vZLHWm1GHVnQawlwI4kbUVCotxHKSTmQYVw7lF2ptwxbd4JoXj7VPFMGp6dqd7fXEWqCOK/zdE/akC7VV9wPAUBcAgY7Vuz+CfD2i2uoQ2+kxzR3qi3uUu5HmSVScnKk47nIAwa+Jnm3J8bbn00Vunm/608zopzUIuDimn959geKP2v7TStauLSL4V+N79YjtM8UNsqsR1xmX9ayv+G0IP+iP+O/+/dp/8dr4813WdV+2hU1zWI40QKkaalMAijgADd0rO/tfV/8AoP61/wCDOf8A+Kq1mlR/b/8AJf8A7Y42tdF/X3H/2Q==
I've also found that I can get that output back to the original string with this one-liner:
await (await (await fetch(output)).blob()).text();
So I've got an output "target" that I know I should be getting, and you have a way to see the original string. So let me explain what I've tried that isn't working.
btoa()
My project is an SSR project which will run on Cloudflare Workers, so I need to be careful that any functions I use are isomorphic.
Since this function is marked as (deprecated) in Node.js, I'd rather find another way to do this, but I tried it anyways. After running btoa(data)
I got this error:
Uncaught DOMException: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.
at <anonymous>:1:1
After some searching, I read that the solution is to instead do btoa(unescape(encodeURIComponent(data)))
:
77+977+977+977+9ABBKRklGAAEBAABIAEgAAO+/ve+/vQDvv71FeGlmAABNTQAqAAAACAAFARIAAwAAAAEAAQAAARoABQAAAAEAAABKARsABQAAAAEAAABSASgAAwAAAAEAAgAA77+9aQAEAAAAAQAAAFoAAAAAAAAASAAAAAEAAABIAAAAAQAD77+9AQADAAAAAQABAADvv70CAAQAAAABAAAAFO+/vQMABAAAAAEAAAANAAAAAO+/ve+/vQA4UGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAAA4QklNBCUAAAAAABDvv70d77+92Y8A77+9BO+/vQnvv73vv73vv71Cfu+/ve+/vQARCAANABQDASIAAhEBAxEB77+977+9AB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC++/ve+/vQDvv70QAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQy77+977+977+9CCNC77+977+9FVLvv73vv70kM2Jy77+9CQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eu+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/vQAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgvvv73vv70A77+9EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIy77+9CBRC77+977+977+977+9CSMzUu+/vRVicu+/vQoWJDTvv70l77+9FxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXrvv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv70AQwADAgIDAgIDAwMDBAMDBAUIBQUEBAUKBwcGCAwKDAwLCgsLDQ4SEA0OEQ4LCxAWEBETFBUVFQwPFxgWFBgSFBUU77+977+9AEMBAwQEBQQFCQUFCRQNCw0UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFO+/ve+/vQAEAALvv73vv70ADAMBAAIRAxEAPwDvv73vv71f77+9F++/vRvvv73vv70l77+977+977+9Pwhq77+9cNuZ77+9aO+/vSDvv73vv73YtO+/vVhGEe+/ve+/vR5A77+977+9AAdx77+977+977+977+977+947eFPC4vZO+/vdabUe+/vVZ0Gu+/vVwI77+9Ru+/vVQqLe+/vXLvv71OZBhXDu+/vRdqbe+/vRbvv73vv73vv70X77+977+9TxTvv73vv73vv73ane+/ve+/ve+/vVrvv73vv70r77+977+9E++/ve+/vQvvv71V77+9A++/vVAXAO+/ve+/vdW7P++/vXw977+977+977+9EO+/ve+/vTHvv70d77+9e++/ve+/ve+/ve+/vUlU77+977+977+9OO+/vXIA77+977+977+977+9be+/ve+/ve+/ve+/vUVu77+9b++/ve+/ve+/ve+/vTUI77+9OO+/ve+/ve+/vX3vv73vv73vv73vv73vv71K1q4tIu+/vVfvv71777+977+977+9M++/vQ3vv73vv70R77+9Ge+/ve+/ve+/ve+/ve+/vW0IP++/ve+/ve+/ve+/ve+/ve+/vX/vv73vv73vv73vv71d77+9dV/vv73vv71Nc1jvv700QO+/vRpqUwDvv704AA3vv70rO++/vV9X77+9AO+/ve+/ve+/ve+/vQDvv70577+9AO+/ve+/ve+/ve+/vVR/b++/vQAl77+9AO+/vTbvv73vv71/X3Hvv73vv70=
However, as you can see, the output is wrong. I'm expecting some string like /9j/4AAQSk...F/X3H/2Q==
based on the "correct" output above, but this string is like 77+977+977...Hvv73vv70=
. Not at all the same.
js-base64
Let's try using a library. Here's what I tried:
import { toBase64 } from "js-base64";
toBase64(data);
However, I get the same incorrect output above. The library does have a urlsafe
argument, though, so I tried that too:
toBase64(data, true);
But that doesn't get me the right output either. I end up with this:
77-977-977-977-9ABBKRklGAAEBAABIAEgAAO-_ve-_vQDvv71FeGlmAABNTQAqAAAACAAFARIAAwAAAAEAAQAAARoABQAAAAEAAABKARsABQAAAAEAAABSASgAAwAAAAEAAgAA77-9aQAEAAAAAQAAAFoAAAAAAAAASAAAAAEAAABIAAAAAQAD77-9AQADAAAAAQABAADvv70CAAQAAAABAAAAFO-_vQMABAAAAAEAAAANAAAAAO-_ve-_vQA4UGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAAA4QklNBCUAAAAAABDvv70d77-92Y8A77-9BO-_vQnvv73vv73vv71Cfu-_ve-_vQARCAANABQDASIAAhEBAxEB77-977-9AB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC--_ve-_vQDvv70QAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQy77-977-977-9CCNC77-977-9FVLvv73vv70kM2Jy77-9CQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eu-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_ve-_vQAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgvvv73vv70A77-9EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIy77-9CBRC77-977-977-977-9CSMzUu-_vRVicu-_vQoWJDTvv70l77-9FxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXrvv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv73vv70AQwADAgIDAgIDAwMDBAMDBAUIBQUEBAUKBwcGCAwKDAwLCgsLDQ4SEA0OEQ4LCxAWEBETFBUVFQwPFxgWFBgSFBUU77-977-9AEMBAwQEBQQFCQUFCRQNCw0UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFO-_ve-_vQAEAALvv73vv70ADAMBAAIRAxEAPwDvv73vv71f77-9F--_vRvvv73vv70l77-977-977-9Pwhq77-9cNuZ77-9aO-_vSDvv73vv73YtO-_vVhGEe-_ve-_vR5A77-977-9AAdx77-977-977-977-977-947eFPC4vZO-_vdabUe-_vVZ0Gu-_vVwI77-9Ru-_vVQqLe-_vXLvv71OZBhXDu-_vRdqbe-_vRbvv73vv73vv70X77-977-9TxTvv73vv73vv73ane-_ve-_ve-_vVrvv73vv70r77-977-9E--_ve-_vQvvv71V77-9A--_vVAXAO-_ve-_vdW7P--_vXw977-977-977-9EO-_ve-_vTHvv70d77-9e--_ve-_ve-_ve-_vUlU77-977-977-9OO-_vXIA77-977-977-977-9be-_ve-_ve-_ve-_vUVu77-9b--_ve-_ve-_ve-_vTUI77-9OO-_ve-_ve-_vX3vv73vv73vv73vv73vv71K1q4tIu-_vVfvv71777-977-977-9M--_vQ3vv73vv70R77-9Ge-_ve-_ve-_ve-_ve-_vW0IP--_ve-_ve-_ve-_ve-_ve-_vX_vv73vv73vv73vv71d77-9dV_vv73vv71Nc1jvv700QO-_vRpqUwDvv704AA3vv70rO--_vV9X77-9AO-_ve-_ve-_ve-_vQDvv70577-9AO-_ve-_ve-_ve-_vVR_b--_vQAl77-9AO-_vTbvv73vv71_X3Hvv73vv70
Buffer.from(data).toString("base64")
Even though this is a Node.js API and doesn't work in my browser, I gave it a try wrapping it in if (import.meta.env.SSR)
, but I get the same 77+977+977...Hvv73vv70=
output from above.
So what am I missing here? How do I get the correct Base64 output? I tried taking the "incorrect" output I got and correctly prefixing it with data:image/jpeg;base64,
, but not surprisingly the browser doesn't render it. What do I need to do to get the same "correct" output which I got when running the image through https://www.base64-image.de?
Don't do this at rutime. Create a loader in your vite.config.ts
const base64Loader: Plugin = {
name: "base64-loader",
transform(_: any, id: string) {
const [path, query] = id.split("?");
if (query != "base64") return null;
const data = fs.readFileSync(path);
const base64 = data.toString("base64");
return `export default '${base64}';`;
},
};
Add it as a plugin
plugins: [ base64Loader, etc...],
Then import the images as base64.
import data from "whatever.jpg?base64"
As an addition to @rvllzzr's answer, you might want to add the following types:
declare global {
declare module "*?base64" {
const value: string;
export = value;
};
}