如何在Next.js项目中将Formidable接收的文件转为Base64并发送至Odoo
Next.js 表单文件直转Base64传Odoo问题解决
问题背景
构建Next.js项目,流程为:前端通过axios将含文件的表单数据以FormData形式发送至后端,后端通过xmlrpc将数据转发至Odoo ERP。核心需求是不将文件存储在服务器,直接转为Odoo兼容的Base64格式发送。
前端代码
const SubmitHandeler = (values) => { const formdata = new FormData(); formdata.append('nom', values.nom); formdata.append('prenom', values.prenom); formdata.append('email', values.email); formdata.append('phone', values.phone); values.files.forEach((file) => { formdata.append(`file`, file); }); setUploading(true); axios.post("/api/upload", formdata, { onUploadProgress: (progressEvent) => { const progressPercent = Math.round( (progressEvent.loaded * 100) / progressEvent.total ); setProgress(progressPercent); }, }).then((result) => { setUploading(false); // router.push('/'); console.log(result.data); }).catch((err) => { setUploading(false); console.log(err) }); }
后端问题
使用formidable解析请求时遇到两个问题:
- 在
formidable.IncomingForm构造函数中设置encoding: "base64",解析得到的文件数组为空 - 不设置编码时,文件数组有内容,但
formidable.File类型的toString()方法无法指定编码转换为Base64(与fs模块的file.toString("base64")行为不同)
后端原代码:
export default async function handeler(req, res) { const form = new formidable.IncomingForm({ multiples: true, encoding: "base64" }); const formData = new Promise((resolve, reject) => { form.parse(req, async (err, fields, files) => { if (err) { reject("error"); } resolve({ fields, files }); }); }); const { fields, files } = await formData; //SEND TO ODOO send_data_to_odoo(/*args*/) res.status(200).json({ msg: "done" }) }
已尝试无效方案
- 使用multer:不符合需求,multer会将文件存储到文件系统
- 前端使用
const base64String = Buffer.from(fileData).toString('base64');转码:无效 - 使用
file.toString():转换结果不被Odoo接受
解决方案
不设置encoding,通过读取formidable生成的临时文件Buffer来转换Base64,转换完成后可删除临时文件避免存储冗余:
import fs from 'fs'; export default async function handler(req, res) { const form = new formidable.IncomingForm({ multiples: true }); // 移除encoding配置 const formData = new Promise((resolve, reject) => { form.parse(req, (err, fields, files) => { if (err) { reject("表单解析失败"); return; } resolve({ fields, files }); }); }); const { fields, files } = await formData; const base64Files = []; // 处理单个或多个文件的情况 const fileList = Array.isArray(files.file) ? files.file : [files.file]; for (const file of fileList) { // 读取临时文件的Buffer const fileBuffer = fs.readFileSync(file.filepath); // 转换为Base64字符串 const base64Str = fileBuffer.toString('base64'); base64Files.push({ filename: file.originalFilename, base64: base64Str, mimetype: file.mimetype }); // 可选:删除临时文件,释放服务器空间 fs.unlinkSync(file.filepath); } // 将字段和Base64文件数据发送至Odoo send_data_to_odoo(fields, base64Files); res.status(200).json({ msg: "done" }); }
说明
- 不设置
encoding,让formidable正常将文件写入临时路径 - 通过
fs.readFileSync读取临时文件的Buffer,再用toString('base64')生成Odoo兼容的Base64字符串 - 转换完成后调用
fs.unlinkSync删除临时文件,避免服务器存储无用文件
内容的提问来源于stack exchange,提问作者Mouayed Keziz
相关产品推荐
相关产品推荐

