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

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 : '未知错误'
    });
  }
}

关键修改点说明

  1. 禁用默认bodyParser:Next.js默认会解析请求体,必须通过export const config禁用,否则Formidable无法获取到原始的multipart数据。
  2. 文件处理逻辑:Formidable解析后的files是包含临时文件路径的对象,需要读取文件内容转为Blob,才能正确添加到FormData中。
  3. 兼容多文件上传:通过Array.isArray判断文件是单个还是数组,统一处理逻辑。
  4. 自动生成Content-Type:手动设置Content-Type: multipart/form-data会丢失boundary标识,导致第三方接口无法解析,fetch会自动处理这一步。
  5. 完善错误处理:增加请求方法校验、第三方接口错误状态捕获,返回更清晰的错误信息。

前端代码小提示

确保你传入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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 23:30:23