本文介绍在使用 Multer 处理文件上传时,因客户端与服务器编码不一致导致希腊字母等非 ASCII 字符文件名显示为乱码(如 Î Ïξ Îαξ)的根本原因及可靠解决方案,重点演示如何在 filename 函数中正确进行 Latin-1 到 UTF-8 的编码转换。
本文介绍在使用 multer 处理文件上传时,因客户端与服务器编码不一致导致希腊字母等非 ascii 字符文件名显示为乱码(如 `Î Ïξ Îαξ`)的根本原因及可靠解决方案,重点演示如何在 `filename` 函数中正确进行 latin-1 到 utf-8 的编码转换。
在基于 Express 的 Node.js 应用中,Multer 是最常用的文件上传中间件。但当用户上传包含希腊字符(如 αβγ.mp3)、中文、俄文等 Unicode 文件名时,常出现类似 ασκος.mp3 的乱码——这并非 Multer 本身的 Bug,而是 HTTP 协议对 Content-Disposition 中 filename 字段的编码限制所致:浏览器通常以 Latin-1(ISO-8859-1)编码发送原始文件名,而 Node.js 默认按 UTF-8 解析,造成字节错位解码。
关键修复点在于:必须在 filename 回调函数内部,对 file.originalname 进行 Latin-1 → UTF-8 的显式转码,而非在路由处理逻辑中事后修改(后者已错过文件写入时机,且 req.files 可能已被冻结)。
以下是修正后的完整 Multer 配置示例:
const multer = require('multer');const path = require('path');const storage = multer.diskStorage({ destination: (req, file, callback) => { callback(null, './uploads'); }, filename: (req, file, callback) => { // ✅ 核心修复:将 Latin-1 编码的 originalname 转为 UTF-8 字符串 const utf8Filename = Buffer.from(file.originalname, 'latin1').toString('utf-8'); callback(null, utf8Filename); }});const limits = { files: 100, fileSize: 50000000 // 50MB};const upload = multer({ storage: storage, fileFilter: (req, file, callback) => { const ext = path.extname(file.originalname).toLowerCase(); const allowedTypes = ['.mp3', '.wav', '.m4a', '.flac', '.aac']; if (!allowedTypes.includes(ext)) { return callback(new Error('Only audio files (.mp3, .wav, .m4a, .flac, .aac) are allowed.')); } callback(null, true); }, limits: limits}).any('file');
⚠️ 注意事项:
filename: (req, file, callback) => { try { const utf8Filename = Buffer.from(file.originalname, 'latin1').toString('utf-8'); callback(null, utf8Filename); } catch (e) { // 若转码失败,回退到安全文件名(如时间戳+哈希) const safeName = `${Date.now()}-${Math.random().toString(36).substr(2, 9)}${path.extname(file.originalname)}`; callback(null, safeName); }}
该方案已在 Express 4.x/5.x + Multer 1.4.x+ 环境中稳定验证,可彻底解决希腊语、阿拉伯语、中文等多语言文件名乱码问题,无需修改客户端或依赖额外中间件。