NextJS 14 Server Page上传文件至外部API时Express端收不到文件
问题:Next.js Server Page 文件上传至Express服务器时req.files为空
重要提示
必须使用Server Page,否则会用客户端组件+axios实现。
尝试将文件上传到外部Express服务器,但API路由接收请求时req.files.file为空、未定义或无内容。
前端检测情况
表单提交触发action时能正常获取到文件,console.log(avatar)输出:
file: File { size: 476026, type: 'image/jpeg', name: 'Delta-Force-Operator-in-a-Chinook_4x-scaled.jpg', lastModified: 1716527617781 }
后端接收问题
Express端使用express-fileupload库,期望通过req.files.file(file是输入框名称)获取文件,但服务器始终接收不到文件,终端打印{}(空对象)。
Express后端代码:
exports.uploadObject = asyncHandler(async (req, res, next) => { // 无文件时终止执行 console.dir(req.files); if (!req.files || Object.keys(req.files).length === 0 || !req.files.file) { return next(new ErrorResponse(`No file uploaded`, 400)); } /* 其他业务逻辑 */ // 返回结果 res.status(201).json({ success: true, data: "success" }); }); }); });
前端Server Page代码
const upgradeAvatar = async (formData) => { 'use server' const avatar = formData.get('file') const rawFormData = { userId: auth?.data?._id, username: auth?.data?.username, userEmail: auth?.data?.email, onModel: 'User', album: 'profile-avatars', file: avatar, } // 输出文件对象,能正常打印 console.log(rawFormData.file); // 调用外部API的函数 await uploadFile(rawFormData) } <form action={upgradeAvatar}> <label htmlFor="file" className="form-label"> File </label> <input id="file" name="file" type="file" className="form-control mb-3" accept={`image/*`} /> <FormButtons /> </form>
解决方法
核心问题是你直接把File对象塞进普通JSON对象传给后端,而express-fileupload只认multipart/form-data格式的请求,不认JSON。
1. 前端重新构建FormData
在upgradeAvatar函数里,放弃普通对象,用FormData实例来包装所有字段和文件:
const upgradeAvatar = async (formData) => { 'use server' const avatar = formData.get('file') const uploadFormData = new FormData(); // 逐一添加非文件字段 uploadFormData.append('userId', auth?.data?._id); uploadFormData.append('username', auth?.data?.username); uploadFormData.append('userEmail', auth?.data?.email); uploadFormData.append('onModel', 'User'); uploadFormData.append('album', 'profile-avatars'); // 添加文件,名称要和后端期望的`file`完全一致 uploadFormData.append('file', avatar); // 调用外部API await uploadFile(uploadFormData) }
2. 修正uploadFile的请求配置
如果uploadFile是你自己封装的函数,注意两点:
- 不要手动设置
Content-Type为application/json,浏览器会自动为FormData生成带边界的multipart/form-data头 - 用POST请求,直接把FormData作为请求体发送
示例uploadFile实现:
async function uploadFile(formData) { const response = await fetch('你的Express API地址', { method: 'POST', body: formData, // 不需要手动设置Content-Type }); return response.json(); }
3. 检查Express中间件顺序
确保express-fileupload中间件在express.json()这类JSON解析中间件之前配置,避免请求被提前解析成JSON:
const express = require('express'); const fileUpload = require('express-fileupload'); const app = express(); // 先配置文件上传中间件 app.use(fileUpload({ createParentPath: true, // 可选,自动创建文件保存目录 })); // 再配置其他中间件 app.use(express.json()); // 挂载上传路由 app.post('/upload', uploadObject);
调整完成后,后端就能通过req.files.file正常获取到上传的文件了。
内容的提问来源于stack exchange,提问作者Kirasiris
相关产品推荐
相关产品推荐

