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

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 _

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 15:51:19