You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nuxt3:如何用FormData+useFetch上传文件至Nitro服务器?

Nuxt Nitro 文件上传处理:替代Multer方案及代码问题排查

当前实现的错误点

  1. 前端请求头问题:使用useFetch提交FormData时,默认会设置Content-Type: application/json,这与multipart/form-data格式冲突,导致后端无法正确解析。正确做法是不手动设置Content-Type,让浏览器自动生成包含boundary的正确请求头。
  2. 后端解析方法错误: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 14:41:31