Node.js控制器无法保存UTF-8编码的阿拉伯语尺寸名称
问题描述
Node.js控制器无法以UTF-8编码保存阿拉伯语尺寸名称,但其余阿拉伯语数据可正常发送至服务器。控制台打印尺寸名称显示正常;提交表单后阿拉伯语字符变为乱码。表单已指定accept-charset="UTF-8",接收的数据打印也正常。
排查与解决方案
1. 修正代码逻辑错误
从提供的代码看,newItem初始化及文件写入逻辑位于upload.single('image')回调函数外部,这会导致变量未定义且执行顺序错误。必须将这部分代码移至upload回调内部,确保文件上传和表单数据解析完成后再执行保存操作。
2. 确保Multer正确解析UTF-8字段名
当表单包含非ASCII字符的字段名(如阿拉伯语尺寸名称)时,需显式配置Multer支持UTF-8编码解析:
const upload = multer({ storage: 你的存储配置, limits: { fieldNameSize: 255 // 确保字段名长度足够容纳阿拉伯语字符 } });
3. 手动解码字段名(可选)
如果Multer仍未正确解析阿拉伯语字段名,可在遍历sizePrice时手动解码:
Object.keys(sizePrice).forEach(encodedSizeName => { const sizeName = decodeURIComponent(encodedSizeName); // 后续处理逻辑 });
4. 验证JSON序列化与文件编码
虽然已在fs.writeFile中指定utf8编码,仍需确保:
JSON.stringify生成的内容不会被错误转义(默认转义为Unicode序列是合法的,读取时会自动解析);- 读取文件时始终指定
utf8编码。
修正后的控制器代码示例
// controllers/menuItemsController.js const fs = require('fs'); const path = require('path'); const MenuItem = require('../../models/MenuItem'); const Category = require('../../models/Category'); const Size = require('../../models/Size'); const dataPaths = require('../../config/data'); const multer = require('multer'); // 配置Multer存储与编码支持 const storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, 'Frontend/img/'); }, filename: function (req, file, cb) { cb(null, Date.now() + '-' + file.originalname); } }); const upload = multer({ storage: storage, limits: { fieldNameSize: 255 } }); function addItem(req, res) { upload.single('image')(req, res, function(err) { if (err instanceof multer.MulterError) { return res.status(500).json({ message: '上传图片时出错' }); } else if (err) { return res.status(500).json({ message: '内部服务器错误' }); } const { category, name, sizes } = req.body; const imageSrc = 'Frontend/img/' + req.file.filename; const sizePrice = req.body.sizePrice; const sizesWithPrices = []; // 处理尺寸名称,确保编码正确 Object.keys(sizePrice).forEach(encodedSizeName => { const sizeName = decodeURIComponent(encodedSizeName); const price = sizePrice[encodedSizeName]; if (price !== '') { sizesWithPrices.push({ name: sizeName, price: parseFloat(price) }); } }); // 执行保存逻辑 const newItem = new MenuItem(category, name, sizesWithPrices, imageSrc); fs.readFile(dataPaths.menuItems, 'utf8', (err, data) => { if (err) { console.error('读取菜单文件出错:', err); return res.status(500).json({ message: '内部服务器错误' }); } const menuItems = JSON.parse(data); menuItems.push(newItem); fs.writeFile(dataPaths.menuItems, JSON.stringify(menuItems, null, 2), 'utf8', (err) => { if (err) { console.error('更新菜单文件出错:', err); return res.status(500).json({ message: '内部服务器错误' }); } res.redirect(`/admincp/menuitems?token=${req.query.token}`); }); }); }); }
内容的提问来源于stack exchange,提问作者yosf.143
相关产品推荐
相关产品推荐

