如何通过Axios实现客户端→服务器→另一服务器的文件上传(Next.js场景)
在Next.js中用Axios转发客户端上传的文件到第三方API
Pages Router 实现(Next.js 12及更早)
由于Pages Router的API路由默认不解析multipart/form-data,需要借助formidable库处理表单数据:
- 先安装依赖:
npm install formidable
- 编写API路由(比如
pages/api/upload-forward.js):
import axios from 'axios'; import formidable from 'formidable'; import fs from 'fs'; // 禁用默认的body解析器,避免与formidable冲突 export const config = { api: { bodyParser: false, }, }; export default async function handler(req, res) { if (req.method !== 'POST') { return res.status(405).json({ error: '仅支持POST请求' }); } const form = new formidable.IncomingForm(); form.parse(req, async (err, fields, files) => { if (err) { return res.status(500).json({ error: '解析表单数据失败' }); } // 获取客户端上传的文件(假设字段名为'file') const uploadedFile = files.file; if (!uploadedFile) { return res.status(400).json({ error: '未上传文件' }); } // 构造转发用的Form Data const forwardFormData = new FormData(); // 以流的形式读取本地临时文件,添加到Form Data中 forwardFormData.append('file', fs.createReadStream(uploadedFile.filepath), { filename: uploadedFile.originalFilename, contentType: uploadedFile.mimetype, }); // 转发其他表单字段(如果有) Object.entries(fields).forEach(([key, value]) => { forwardFormData.append(key, value); }); try { // 发送请求到目标API const response = await axios.post('https://目标API端点地址', forwardFormData, { headers: { ...forwardFormData.getHeaders(), // 自动生成multipart/form-data的请求头 // 按需添加目标API所需的其他头,比如认证令牌 // 'Authorization': 'Bearer YOUR_ACCESS_TOKEN' }, }); // 将目标API的响应返回给客户端 res.status(response.status).json(response.data); } catch (error) { res.status(error.response?.status || 500).json({ error: error.response?.data?.message || '转发文件失败', }); } }); }
App Router 实现(Next.js 13+)
App Router基于Web标准API,可以直接用request.formData()解析表单,无需额外依赖:
编写API路由(比如app/api/upload-forward/route.js):
import axios from 'axios'; export async function POST(request) { try { // 解析客户端发送的Form Data const clientFormData = await request.formData(); const file = clientFormData.get('file'); if (!file) { return Response.json({ error: '未上传文件' }, { status: 400 }); } // 构造转发用的Form Data const forwardFormData = new FormData(); forwardFormData.append('file', file); // 转发其他表单字段 clientFormData.forEach((value, key) => { if (key !== 'file') { forwardFormData.append(key, value); } }); // 发送请求到目标API const response = await axios.post('https://目标API端点地址', forwardFormData, { headers: { ...forwardFormData.getHeaders(), // 按需添加目标API所需的认证头或其他头 }, }); return Response.json(response.data, { status: response.status }); } catch (error) { return Response.json( { error: error.response?.data?.message || '转发文件失败' }, { status: error.response?.status || 500 } ); } }
关键注意事项
- 字段名匹配:确保转发时Form Data的字段名(比如示例中的'file')与目标API要求的一致。
- 请求头设置:必须通过
forwardFormData.getHeaders()自动生成Content-Type头,手动设置可能会遗漏boundary参数导致解析失败。 - 错误处理:捕获Axios请求的错误,将目标API的错误信息或通用错误返回给客户端,便于调试。
- 临时文件清理:Pages Router中
formidable会生成临时文件,若需要可在请求完成后调用fs.unlink(uploadedFile.filepath)清理(需额外处理异步逻辑)。
内容的提问来源于stack exchange,提问作者Nikhil Kumar
相关产品推荐
相关产品推荐

