Next.js 14 Server Actions处理Multipart FormData及获取文件路径
Next.js 14 Server Action + Formidable:获取临时文件路径与Request对象
1. 获取Request对象(对应Express的req)
在Next.js 14的Server Action中,直接调用request()函数就能拿到当前请求的Request对象,功能和Express里的req对应。注意必须在异步Server Action中调用,且项目需启用App Router(Server Action默认在App Router中支持)。
2. 用Formidable解析文件并获取临时路径
Formidable默认会把上传的文件写入系统临时目录,解析完成后,你可以从返回的files对象中提取filepath字段,这就是临时文件的绝对路径,和Express中Formidable返回的路径格式一致。
完整代码示例
客户端组件(上传文件)
'use client'; export default function UploadPage() { const handleUpload = async (e: React.FormEvent<HTMLFormElement>) => { e.preventDefault(); const formData = new FormData(e.currentTarget); try { await uploadImageConverter(formData); alert('文件上传成功'); } catch (err) { console.error('上传失败:', err); } }; return ( <form onSubmit={handleUpload}> <input type="file" name="image" accept="image/*" /> <button type="submit">上传图片</button> </form> ); }
Server Action(处理上传)
'use server'; import { formidable } from 'formidable'; import fs from 'fs/promises'; import path from 'path'; export async function uploadImageConverter(formData: FormData) { // 获取当前请求的Request对象 const req = await request(); // 配置Formidable const form = formidable({ keepExtensions: true, // 保留文件扩展名 // 可选:自定义临时目录,默认是系统temp文件夹 // uploadDir: path.join(process.cwd(), 'tmp'), }); // 解析Request对象 const { fields, files } = await form.parse(req); // 获取上传的文件(假设表单中文件字段名为"image") const imageFile = files.image?.[0]; if (!imageFile) throw new Error('未选择文件'); // 临时文件路径,和Express中拿到的格式一致 console.log('临时文件路径:', imageFile.filepath); // 示例:将临时文件移动到项目的public/uploads目录(可选操作) const targetPath = path.join(process.cwd(), 'public/uploads', imageFile.originalFilename || 'unknown-file'); await fs.copyFile(imageFile.filepath, targetPath); // 可选:删除临时文件(Formidable默认不会自动删除,需手动清理) await fs.unlink(imageFile.filepath); return { success: true, filePath: targetPath }; }
关键说明
- Formidable版本:确保安装
formidable@^3.x,v2版本API和示例代码不兼容。 - 临时文件清理:Formidable不会自动删除临时文件,处理完成后记得用
fs.unlink删除,避免占用磁盘空间。 - Request对象权限:
request()只能在Server Action或Server Component中调用,客户端组件无法直接使用。
内容的提问来源于stack exchange,提问作者elias-soykat
相关产品推荐
相关产品推荐

