Express结合Multer文件上传时originalname文件名编码错误修复
问题现象
上传文件名为😀😉.jpg的文件时,服务端读取到的原始文件名为乱码ðð.jpg。
前端实现代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <form action="/form" method="post" enctype="multipart/form-data" accept-charset="UTF-8" > <input type="file" name="avatar" /> <button>Send</button> </form> </body> </html>
初始服务端实现代码:
import express from "express"; import dotenv from "dotenv"; import multer from "multer"; dotenv.config() const app = express(); app.use(express.urlencoded({extended:true})) app.use(express.json()); const upload = multer({ dest: 'uploads/' }) app.get("/:id?", async (req,res,next)=>{ res.sendFile("views/index.html", {root: __dirname }) }) app.post("/form", upload.fields([{ name: 'avatar', maxCount: 1 }]), async (req, res, next)=>{ res.send(req.files['avatar']? req.files['avatar'][0].originalname : 'Error'); }) app.listen(process.env.PORT, async ()=>{ console.log("Server start at "+process.env.PORT) })
乱码原因
- 浏览器提交
multipart/form-data表单时遵循RFC 7578规范,默认使用UTF-8编码传输文件名,emoji等多字节字符会按UTF-8规则拆分为多个字节传输。 - 旧版
multer依赖的busboy解析层默认使用*latin1(ISO-8859-1)*单字节编码解析文件名,会将UTF-8的多字节序列按单个字节逐一映射为latin1字符,最终生成乱码。你看到的ð字符就是UTF-8编码首字节被单字节解码的典型结果。 - 前端已正确声明UTF-8编码,故障点完全在服务端解析层的编码配置,和前端逻辑无关。
修复方案
两种方案二选一即可,优先选择第一种配置式方案,维护成本更低。
方案1:显式配置multer使用UTF-8解析
初始化multer实例时传入编码参数,指定底层解析器使用UTF-8处理所有表单字段、文件名:
// 原初始化代码 // const upload = multer({ dest: 'uploads/' }) // 修改为 const upload = multer({ dest: 'uploads/', encoding: 'utf-8' })
该配置会直接透传给底层busboy解析器,修改后所有中文、emoji文件名都可以被正确解析,不需要额外处理单个文件的文件名。
方案2:手动转码兼容旧依赖版本
如果受项目依赖版本限制无法通过配置解决,可以在读取到文件名后手动转码还原:
app.post("/form", upload.fields([{ name: 'avatar', maxCount: 1 }]), async (req, res, next)=>{ if (!req.files['avatar']) return res.send('Error') const file = req.files['avatar'][0] // 按latin1编码还原原始二进制,再用UTF-8解码得到正确文件名 const originalName = Buffer.from(file.originalname, 'latin1').toString('utf8') res.send(originalName) })
该转码逻辑可以完全还原被错误解析的多字节字符,兼容所有版本的multer。
内容的提问来源于stack exchange,提问作者Alex _
相关产品推荐
相关产品推荐

