You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 22:33:22