Nuxt3:如何用FormData+useFetch上传文件至Nitro服务器?
Nuxt Nitro 文件上传处理:替代Multer方案及代码问题排查
当前实现的错误点
- 前端请求头问题:使用
useFetch提交FormData时,默认会设置Content-Type: application/json,这与multipart/form-data格式冲突,导致后端无法正确解析。正确做法是不手动设置Content-Type,让浏览器自动生成包含boundary的正确请求头。 - 后端解析方法错误:
readBody仅适用于解析JSON或URL编码的请求体,无法处理包含文件的multipart/form-data,因此你无法通过它获取到文件内容。
Nitro中替代Multer的方案
Nitro基于h3框架,提供了原生的readMultipartFormData方法来解析包含文件的表单数据,无需额外引入Multer类工具。如果需要更封装化的功能,也可以使用社区包(如@sidebase/nuxt-upload),但原生方法已能满足基础需求。
修正后的完整代码
前端组件代码
const { data, pending } = useFetch("/api/product", { method: "post", body: fd, // fd为已包含文件的FormData实例 // 不要手动设置Content-Type,浏览器会自动添加正确的multipart/form-data请求头 })
后端API代码(~/server/api/product.post.ts)
import { defineEventHandler, readMultipartFormData } from "h3"; import { writeFileSync, mkdirSync } from "fs"; import { join } from "path"; export default defineEventHandler(async (event) => { // 解析multipart表单数据 const formItems = await readMultipartFormData(event); if (!formItems) { return { status: false, text: "未接收到有效表单数据" }; } // 确保上传目录存在 const uploadDir = join(process.cwd(), "public", "uploads"); mkdirSync(uploadDir, { recursive: true }); // 遍历处理每个表单项 for (const item of formItems) { if (item.filename) { // 处理文件项:写入服务器指定目录 const filePath = join(uploadDir, item.filename); writeFileSync(filePath, item.data); } else { // 处理普通表单字段 console.log(`字段 ${item.name} 的值:`, item.data.toString()); } } return { status: true, text: "保存成功!" }; })
额外说明
readMultipartFormData返回的每个表单项包含:name(字段名)、filename(仅文件项存在)、data(Buffer类型,存储文件内容或字段值)。- 可以在遍历过程中添加文件校验逻辑,比如限制文件大小、允许的文件类型。
- 若需要更高级的上传功能(如断点续传、云存储集成),可以考虑使用
@sidebase/nuxt-upload这类封装好的社区包。
内容的提问来源于stack exchange,提问作者Taha Gharache
相关产品推荐
相关产品推荐

