如何将Vite中导入的原始图片编码为Base64?
你遇到的核心问题是:用?raw导入二进制图片(JPG)时,Vite会把二进制数据当作UTF-8字符串解码,这一步已经破坏了原始二进制信息,后续无论用哪种base64编码工具,都基于错误的字符串处理,自然得不到正确结果。
最优解决方案:直接用Vite原生的?base64导入
Vite内置了对二进制文件的base64导入支持,完全适配同构场景(包括Cloudflare Workers),无需手动编码:
// 直接导入图片的base64编码字符串 import imgBase64 from "whatever.jpg?base64"; // 拼接成Data URI const dataUri = `data:image/jpeg;base64,${imgBase64}`;
这个方案最可靠,因为Vite会直接读取原始二进制数据并编码为base64,跳过了错误的UTF-8解码步骤,结果和你用在线工具得到的一致。
如果你不需要手动拼接Data URI,也可以用?url导入:
import imgUrl from "whatever.jpg?url"; // 对于小文件(默认阈值是4KB),Vite会自动生成Data URI作为url值 // 直接使用imgUrl即可,无需额外处理
为什么之前的方法都失败了?
btoa()相关尝试:- 直接调用
btoa(data)报错,是因为?raw导入的字符串包含UTF-8解码后产生的、超出Latin1范围的字符(JPG二进制不是合法UTF-8文本)。 btoa(unescape(encodeURIComponent(data)))是处理合法UTF-8字符串的base64编码方法,但你的data是二进制被错误解码的产物,所以编码结果必然错误。
- 直接调用
js-base64库:
该库的toBase64方法默认基于UTF-8处理字符串,同样无法还原被错误解码的二进制数据,结果自然不对。Buffer.from(data).toString("base64"):Buffer.from(data)默认用UTF-8编码解析字符串,和上面的问题一样,基于错误的字符串生成Buffer,编码结果错误。即使指定'latin1'编码,也无法还原原始二进制(因为JPG字节不是Latin1字符集)。
特殊场景:必须用?raw导入的处理方案
如果因为特殊需求必须用?raw导入,需要先将错误解码的UTF-8字符串还原为原始二进制数据,再进行base64编码:
// 将UTF-8字符串还原为Uint8Array function strToUint8Array(str) { return new TextEncoder().encode(str); } // 将Uint8Array转换为base64 function uint8ArrayToBase64(arr) { return btoa(String.fromCharCode(...arr)); } import data from "whatever.jpg?raw"; const rawBinary = strToUint8Array(data); const base64 = uint8ArrayToBase64(rawBinary); const dataUri = `data:image/jpeg;base64,${base64}`;
注意:这个方案仅在二进制数据被UTF-8解码时没有丢失信息的情况下有效(比如所有字节都在UTF-8可表示范围内),但JPG可能包含无法被UTF-8正确解码的字节,因此仍推荐优先使用?base64导入方案。
内容的提问来源于stack exchange,提问作者Aaron Beaudoin

