使用axios上传UTF-8文件名文件时Multer损坏文件名的解决方法
Axios 向 Multer 上传带 UTF-8 文件名文件的正确实现
问题根因
已验证Chrome原生发送的multipart/form-data请求编码正常,乱码核心原因是旧版本Axios(1.0以下)处理FormData时未遵循RFC 5987规范传递UTF-8文件名声明,还会对文件名做错误的Latin-1编码转换,导致Multer解析时无法正确识别中文等非ASCII文件名。
正确实现步骤
前端Axios侧(核心修复)
- 不要手动设置
Content-Type请求头,Axios/浏览器会自动生成带正确boundary分隔符的请求头,手动指定会导致分隔符丢失、请求解析失败 - 不要对文件名做
encodeURI/encodeURIComponent转码,直接传入原始UTF-8文件名即可 - 旧版本Axios需配置transformRequest移除错误的默认头设置
参考代码:
// 构造标准FormData实例 const formData = new FormData(); // 第三个参数直接传入原始UTF-8文件名,无需转码 formData.append('uploadFile', fileInstance, '项目立项说明_中文文件名.docx'); // 发送POST请求 const uploadRes = await axios.post('/api/upload', formData, { // Axios <1.0 版本必须加以下配置,1.0+版本可省略 transformRequest: [(data, headers) => { delete headers['Content-Type']; return data; }] });
常见踩坑:如果手动把文件名做URL编码再传入,Multer拿到的会是转义后的字符串,反而出现乱码,和Chrome原生上传行为保持一致即可。
后端Multer侧(兜底配置)
Multer默认已支持UTF-8文件名解析,自定义存储逻辑时不要做多余的编码转换即可:
const multer = require('multer'); const uploadInstance = multer({ storage: multer.diskStorage({ destination: (req, file, cb) => cb(null, './public/upload/'), filename: (req, file, cb) => { // file.originalname 就是解析完成的正确UTF-8文件名,直接使用即可 // 不要做Buffer转码、URL解码等多余操作 cb(null, `${Date.now()}_${file.originalname}`); } }) }); // 路由中使用 app.post('/api/upload', uploadInstance.single('uploadFile'), (req, res) => { res.send({ code: 0, msg: '上传成功', data: req.file }); });
校验标准
打开浏览器DevTools的Network面板,查看对应上传请求的Payload,multipart分段中filename字段直接显示原始中文文件名即为配置正确,示例正常分段格式:
------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="uploadFile"; filename="项目立项说明_中文文件名.docx" Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document
如果filename字段显示乱码、或带%开头的转义字符,说明前端配置存在问题。
内容的提问来源于stack exchange,提问作者Marc Kornberger
相关产品推荐
相关产品推荐

