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

如何通过NextJS API路由携带JWT将上传图片转发至外部DRF接口

问题背景
  • 项目技术栈:前端基于NextJS搭建,鉴权后仪表盘同时支持SSR与SPA渲染模式,后端服务使用Django Rest Framework
  • 现有鉴权逻辑:JWT令牌存储在Cookie中,/pages/api/*路径下所有请求通过中间件从Cookie读取access令牌,追加到转发给后端的请求头中
  • 待实现需求:完成受保护的文件上传逻辑,当前端将图片文件提交到/pages/api/upload接口时,接口需要携带用户access令牌,将文件正确转发到DRF后端
现有普通GET请求转发参考代码
export default async (req, res) => {
  const { id } = req.query
  const cookies = cookie.parse(req.headers.cookie ?? "");
  const access = cookies["access"] ?? false;
  if (access === false) {
    return res.status(401).json({
      error: "User unauthorized to make this request"
    });
  }

  if (req.method === "GET") {
    try {
      const apiRes = await fetch(`${LOCAL_API_URL}/items/${id}`, {
        headers: {
          "Accept": "application/json",
          "Content-Type": "application/json",
          "Authorization": `Bearer ${access}`
        }
      });
      const data = await apiRes.json();
      if (apiRes.status === 200) {
        return res.status(200).json(data);
      } else {
        return res.status(apiRes.status).json({
          error: data.error
        });
      }
    } catch(err) {
      console.log(err);
      return res.status(500).json({
        error: "Something went wrong"
      });
    }
  } else
    res.setHeader("Allow", ["GET"]);
  return res.status(405).json({
    error: `Method ${res.method} is not allowed`
  });
}
文件上传转发实现方案

文件上传请求和普通JSON请求的核心差异是请求体为multipart/form-data格式,转发时不能直接套用JSON请求的头配置,核心注意点是不能手动设置Content-Type请求头,必须让运行环境自动生成带boundary分隔符的合法头,否则DRF后端无法解析文件内容。

完整实现代码

import cookie from 'cookie'

// 关键配置:关闭NextJS默认的请求体解析,保留原始FormData流
export const config = {
  api: {
    bodyParser: false,
  },
}

export default async (req, res) => {
  // 复用原有鉴权逻辑
  const cookies = cookie.parse(req.headers.cookie ?? "");
  const access = cookies["access"] ?? false;
  if (!access) {
    return res.status(401).json({
      error: "User unauthorized to make this request"
    });
  }

  // 限制仅允许POST方法访问上传接口
  if (req.method !== "POST") {
    res.setHeader("Allow", ["POST"]);
    return res.status(405).json({
      error: `Method ${req.method} is not allowed`
    });
  }

  try {
    const apiRes = await fetch(`${process.env.LOCAL_API_URL}/upload/`, {
      method: "POST",
      headers: {
        "Accept": "application/json",
        "Authorization": `Bearer ${access}`,
        // 透传content-length头适配大文件传输校验
        ...(req.headers["content-length"] && {
          "Content-Length": req.headers["content-length"]
        })
        // 禁止手动添加Content-Type头,fetch会自动生成带boundary的合法multipart头
      },
      // 直接透传原始请求流,不需要重新构造FormData,性能最优
      body: req,
      // Node 18+ 原生fetch传递流body必须添加该配置
      duplex: 'half'
    });

    const data = await apiRes.json();
    // 透传后端返回的状态码和响应内容
    return res.status(apiRes.status).json(data);
  } catch(err) {
    console.error("File upload forward error:", err);
    return res.status(500).json({
      error: "Something went wrong during file upload"
    });
  }
}

关键注意事项

  • 必须关闭NextJS默认bodyParser:默认解析逻辑会把请求体转换成普通JS对象,丢失文件二进制流信息,直接导致转发失败
  • 禁止手动设置Content-Type:multipart/form-data请求需要携带动态生成的boundary参数分隔不同表单字段,手动设置头会丢失该参数,DRF会返回文件解析错误
  • 优先使用流透传方案:直接把req对象作为fetch的请求体,不需要在NextJS服务端把整个文件加载到内存,大文件场景下内存占用更低、传输速度更快
  • 如果需要做文件校验(格式、大小、文件名合规性),可以在转发前通过流解析完成校验,校验通过后再透传给后端即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 02:18:03