如何通过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
相关产品推荐
相关产品推荐

