可靠的图片预览包含两个独立步骤:解码 Base64,再解码图片格式。字符串可以通过第一步,却因为截断、类型错误或浏览器不支持而无法显示。界面应区分这些状态。
始终以字节为中间结果
通过解析器移除已识别的 Data URI,校验 Base64,然后得到 Uint8Array。不要让图像字节经过文本解码器。本地预览可以将字节封装为 Blob,再生成对象 URL,避免为了显示而重新构造很长的 Base64。
async function previewRaster(bytes, type, imageElement) {
const allowed = ['image/png', 'image/jpeg', 'image/webp', 'image/gif'];
if (!allowed.includes(type)) throw new Error('不支持的位图预览类型');
const url = URL.createObjectURL(new Blob([bytes], { type }));
try {
imageElement.src = url;
await imageElement.decode();
return { width: imageElement.naturalWidth, height: imageElement.naturalHeight,
dispose: () => URL.revokeObjectURL(url) };
} catch (error) {
URL.revokeObjectURL(url);
imageElement.removeAttribute('src');
throw error;
}
}
及时释放对象 URL
替换或移除预览时调用返回的 dispose。反复预览却不清理会占用浏览器资源。不要在加载完成之前释放,也不要把已释放的 URL 用于后续下载。下载需要继续可用时,应单独管理生命周期。
使用真实图片解码反馈
文件头只是初步线索。图像元素的 decode 可以检查浏览器是否能加载,并获得尺寸。此处失败时,应说明图片解码失败,同时保留原始字节供检查或下载,而不是误报 Base64 字母表错误。
尽可能在昂贵渲染前限制字节和尺寸,小型压缩文件也可能展开为巨大图片。SVG 属于结构化标记,不能与普通位图一视同仁,更不能直接把未知 SVG 或 HTML 插入页面。
预览与转换也不同:显示 JPEG 不会产生 PNG。转换需要将解码图像绘制到画布,再按目标格式导出,并明确质量和透明度选择。Data URI 语法见 MDN: data URLs;预览成功只是浏览器格式检查,不是通用安全认证。