如何将 Vite 中导入的“原始”图像编码为 Base64?

问题描述 投票:0回答:1

我有一个JPG,我像

import data from "whatever.jpg?raw";
一样导入到Vite中。我的目标是将生成的原始 JPEG 字符串编码为数据 URI,如
data:image/jpeg;base64,DATA
。 JPEG 非常小(20x13,1 KB),因此大小不应该成为问题。问题是我不知道如何获得正确的输出。

我对“正确”输出应该是什么样子的想法来自于通过 https://www.base64-image.de 运行 JPEG,并且我已经能够验证我的浏览器是否正确呈现该输出。这是:

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==

我还发现我可以使用这一行将输出返回到原始字符串:

await (await (await fetch(output)).blob()).text();

所以我得到了一个我知道应该得到的输出“目标”,并且您有办法查看原始字符串。那么让我解释一下我尝试过但不起作用的方法。

1.
btoa()

我的项目是一个将在 Cloudflare Workers 上运行的 SSR 项目,因此我需要小心,我使用的任何函数都是同构。 由于此函数在 Node.js 中被标记为(已弃用),因此我宁愿寻找另一种方法来执行此操作,但我还是尝试了它。运行后

btoa(data)
我得到了这个错误:

Uncaught DOMException: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.
    at <anonymous>:1:1

经过一番搜索,我读到解决方案是这样做

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=

但是,正如您所看到的,输出是错误的。我期待一些像

/9j/4AAQSk...F/X3H/2Q==
这样的字符串基于上面的“正确”输出,但这个字符串就像
77+977+977...Hvv73vv70=
。完全不一样。

2.
js-base64

让我们尝试使用库。这是我尝试过的:

import { toBase64 } from "js-base64";

toBase64(data);

但是,我得到了上面相同的错误输出。不过,该库确实有一个

urlsafe
参数,所以我也尝试了:

toBase64(data, true);

但这也没有给我带来正确的输出。我最终得到的是这个:

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

3.
Buffer.from(data).toString("base64")

尽管这是一个 Node.js API 并且在我的浏览器中不起作用,我尝试将其包装在

if (import.meta.env.SSR)
中,但我从上面得到了相同的
77+977+977...Hvv73vv70=
输出。

那么我在这里缺少什么?如何获得正确的 Base64 输出?我尝试获取得到的“不正确”输出,并正确地在其前面加上

data:image/jpeg;base64,
前缀,但毫不奇怪,浏览器不会渲染它。我需要做什么才能获得与通过 https://www.base64-image.de 运行图像时获得的相同“正确”输出?

javascript base64 vite data-uri isomorphic-javascript
1个回答
0
投票

不要在紧急时刻这样做。在你的 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}';`;
  },
};

将其添加为插件

plugins: [ base64Loader, etc...],

然后将图像导入为base64。

import data from "whatever.jpg?base64"
© www.soinside.com 2019 - 2024. All rights reserved.