头像从 base64 改成文件存储
最早的实现很省事:头像上传后转成 base64 字符串,直接存进数据库字段。开发环境跑得很好,直到有人传了一张 3MB 的原图。
那个字段里存进去是四百万字符(base64 比原图大三分之一)。后果不是一条数据慢,是所有的查询都慢——列表接口的 SELECT 里带上了这个字段,一次取十行就是四十兆字符在网络上跑。我一开始怀疑是索引失效,因为现象确实像"加了数据之后突然变慢"。
改法分三步。
存文件。上传时写进 uploads 目录,数据库只存路径。文件名用随机 UUID,避免重名覆盖(这是另一个坑,见 multer 那篇)。
迁移历史数据。写一个脚本把已有的 base64 解码成文件、更新路径字段,跑完再删列。顺序不能反:先删列,历史数据就没了。
把字段从默认查询里排除。列表接口只需要头像路径,Prisma 的 select 明确列出要哪些字段,别用默认的全字段返回。
现在回头看,base64 唯一适合存的场景是"小于几 KB 且不需要单独访问"的图,比如签名、二维码。头像不属于这一类,因为它要能被 <img src> 直接引用、要能被缓存、要能单独换。
还有一条:改成文件存储之后,备份要跟着改。数据库 dump 里不再包含图片,图片在卷里,得单独备。这件事我是在第一次做恢复演练时才发现漏了的。