Next.js 13中使用Formidable转换结果为FormData的图片上传问题求助
解决方案
你的核心问题是Formidable解析后的文件对象不能直接添加到新的FormData中,需要读取文件内容并以正确的格式传入。以下是修正后的完整代码及说明:
后端接口修正(pages/api/upload-image.tsx)
首先必须禁用Next.js默认的请求体解析器,让Formidable处理multipart/form-data类型的请求。然后正确读取解析后的文件内容,添加到新的FormData再转发:
import type { NextApiRequest, NextApiResponse } from 'next'; import formidable from 'formidable'; import fs from 'fs/promises'; // 禁用Next.js默认的body解析,否则Formidable无法处理上传文件 export const config = { api: { bodyParser: false, }, }; export default async function handler(req: NextApiRequest, res: NextApiResponse) { // 仅允许POST请求 if (req.method !== 'POST') { return res.status(405).json({ message: '仅支持POST请求' }); } const form = new formidable.Formidable({ multiples: true }); try { // 解析请求体 const { fields, files } = await new Promise<{ fields: formidable.Fields; files: formidable.Files }>((resolve, reject) => { form.parse(req, (err, fields, files) => { if (err) reject(err); else resolve({ fields, files }); }); }); const forwardFormData = new FormData(); // 兼容单个/多个文件上传的情况 const targetFiles = Array.isArray(files.file) ? files.file : [files.file]; // 遍历文件,读取内容并添加到FormData for (const file of targetFiles) { // 读取本地临时文件内容 const fileBuffer = await fs.readFile(file.filepath); // 创建Blob对象(Node.js 18+原生支持) const fileBlob = new Blob([fileBuffer], { type: file.mimetype }); // 添加到FormData,指定文件名保持原始上传名称 forwardFormData.append('file', fileBlob, file.originalFilename || 'unknown-file'); } // 转发到第三方接口 const thirdPartyResponse = await fetch('https://example.tco', { method: 'POST', body: forwardFormData, headers: { Authorization: 'dfghgjghdgsfa345', // 请勿手动设置Content-Type,fetch会自动生成包含boundary的正确头 }, }); // 处理第三方接口错误 if (!thirdPartyResponse.ok) { throw new Error(`第三方接口请求失败: ${thirdPartyResponse.statusText}`); } const responseData = await thirdPartyResponse.json(); res.status(200).json(responseData); } catch (err) { console.error('上传转发失败:', err); res.status(500).json({ message: '上传转发失败', error: err instanceof Error ? err.message : '未知错误' }); } }
关键修改点说明
- 禁用默认bodyParser:Next.js默认会解析请求体,必须通过
export const config禁用,否则Formidable无法获取到原始的multipart数据。 - 文件处理逻辑:Formidable解析后的
files是包含临时文件路径的对象,需要读取文件内容转为Blob,才能正确添加到FormData中。 - 兼容多文件上传:通过
Array.isArray判断文件是单个还是数组,统一处理逻辑。 - 自动生成Content-Type:手动设置
Content-Type: multipart/form-data会丢失boundary标识,导致第三方接口无法解析,fetch会自动处理这一步。 - 完善错误处理:增加请求方法校验、第三方接口错误状态捕获,返回更清晰的错误信息。
前端代码小提示
确保你传入FormData的是真实的文件对象,比如从文件选择器获取:
// 示例:从input获取文件 const fileInput = document.querySelector('input[type="file"]'); if (fileInput.files.length > 0) { const body = new FormData(); body.append('file', fileInput.files[0]); fetch('/api/upload-image', { method: 'POST', body, }) .then(res => res.json()) .then(data => console.log(data)) .catch(err => console.error(err)); }
内容的提问来源于stack exchange,提问作者Riky Andreas
相关产品推荐
相关产品推荐

