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

NextJS API作为中间层转发带文件的FormData到后端的问题

核心原因

NextJS API路由默认开启的内置请求体解析器不支持处理multipart/form-data类型的文件上传请求,会破坏原始FormData结构,同时直接将普通对象作为fetch的body参数也不符合后端接收FormData格式的要求。

解决方案

场景1:不需要修改请求内容,直接透传(推荐,性能最优)

无需额外依赖,直接禁用内置请求体解析后将原始请求流转发给后端即可:

import { getAccessToken, withApiAuthRequired } from "@auth0/nextjs-auth0";

export default withApiAuthRequired(async function brands(req, res) {
  const { accessToken } = await getAccessToken(req, res, {});
  
  try {
    const upstreamResponse = await fetch("http://localhost:5000/brands", {
      method: "POST",
      headers: {
        Authorization: `Bearer ${accessToken}`,
        // 透传原请求的Content-Type,包含multipart格式的边界分隔符信息
        "Content-Type": req.headers["content-type"],
      },
      // 直接传入原始请求作为body,无需解析重打包
      body: req,
    });

    const result = await upstreamResponse.json();
    // 透传上游返回的状态码和响应内容
    res.status(upstreamResponse.status).json(result);
  } catch (err) {
    res.status(500).json({ error: "请求转发失败" });
  }
});

// 禁用NextJS默认的请求体解析
export const config = {
  api: {
    bodyParser: false,
  },
};

场景2:需要修改FormData字段后再转发

如果需要在转发前增删修改请求字段,可以先解析原始FormData,调整后重新构建FormData再转发,需要先安装依赖:
npm install formidable form-data

对应API代码:

import { getAccessToken, withApiAuthRequired } from "@auth0/nextjs-auth0";
import formidable from "formidable";
import FormData from "form-data";
import fs from "fs";

export default withApiAuthRequired(async function brands(req, res) {
  const { accessToken } = await getAccessToken(req, res, {});
  
  // 解析原始FormData
  const form = formidable({});
  const [fields, files] = await form.parse(req);
  
  // 构建新的FormData
  const formData = new FormData();
  // 追加普通字段,可根据需求修改字段值
  formData.append("title", fields.title[0]);
  formData.append("slug", fields.slug[0]);
  formData.append("bio", fields.bio[0]);
  // 追加文件字段
  formData.append("logo", fs.createReadStream(files.logo[0].filepath), files.logo[0].originalFilename);
  
  try {
    const upstreamResponse = await fetch("http://localhost:5000/brands", {
      method: "POST",
      headers: {
        Authorization: `Bearer ${accessToken}`,
        // 自动生成带边界的FormData请求头
        ...formData.getHeaders(),
      },
      body: formData,
    });

    const result = await upstreamResponse.json();
    res.status(upstreamResponse.status).json(result);
  } catch (err) {
    res.status(500).json({ error: "请求处理失败" });
  }
});

// 禁用默认请求体解析
export const config = {
  api: {
    bodyParser: false,
  },
};
注意事项
  • 如果使用NextJS 13+ App Router的路由处理器,默认不会解析请求体,可直接读取request.body作为流透传,无需额外配置禁用bodyParser。
  • 透传multipart请求时不可手动指定Content-Type为固定值,必须携带自动生成的边界信息,否则后端无法正常解析FormData。

内容的提问来源于stack exchange,提问作者elijah

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 15:51:01