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

Nuxt3 useFetch POST请求:服务端API路由丢失File对象

问题描述
  • 客户端侧的数据包含完整的File对象
  • 服务端返回的请求体为空对象
    问题截图
    请问我的File对象去向何处?

客户端上传代码

const handleImageUpload = async (evt: Event) => {
  const target = evt.target as HTMLInputElement 
  if (target.files) {

    const file = target.files[0]

    const upload: iUpload = {
      name: file.name,
      type: file.type,
      file
    }

    console.log("data from client", upload)
    try {

      const { data, error } = await useFetch(constants.imageUploadApiUrl, {
        headers: { "Content-type": "application/json" },
        method: 'POST',
        body: upload
      })
 
      console.log("data from server", data.value)
    } catch (error) {
      console.log(error)
    }

  }
}

服务端API路由代码

import { getQuery, readBody } from "h3"
import { iUpload } from "~~/helpers/interfaces"

export default defineEventHandler(async (event) => {

  try {
    const query = getQuery(event)
    const body = await readBody(event) as iUpload
    return { body }
  } catch (error: any) {
    return { error: error.message }
  }
})

iUpload接口定义

export interface iUpload {
  name: string;
  type: string;
  file: File;
}

问题原因与解决方案

问题原因

你用Content-type: application/json提交请求,但File对象无法被JSON序列化。当JSON.stringify处理包含File的对象时,会把File转为空对象{},导致服务端接收到的请求体为空。

解决方案

文件上传必须用multipart/form-data格式,改用FormData包装数据:

1. 修改客户端代码

const handleImageUpload = async (evt: Event) => {
  const target = evt.target as HTMLInputElement 
  if (target.files) {
    const file = target.files[0]
    const formData = new FormData()
    // 追加文件与字段
    formData.append('file', file)
    formData.append('name', file.name)
    formData.append('type', file.type)

    console.log("data from client", formData)
    try {
      const { data, error } = await useFetch(constants.imageUploadApiUrl, {
        method: 'POST',
        body: formData
        // 无需手动设置Content-type,浏览器会自动添加带边界标识的multipart/form-data
      })
 
      console.log("data from server", data.value)
    } catch (error) {
      console.log(error)
    }
  }
}

2. 修改服务端API代码

用h3的readMultipartFormData解析FormData:

import { getQuery, readMultipartFormData } from "h3"
import { writeFile } from 'fs/promises'
import { join } from 'path'

export default defineEventHandler(async (event) => {
  try {
    const query = getQuery(event)
    const formData = await readMultipartFormData(event)
    if (!formData) {
      return { error: '未接收到表单数据' }
    }

    // 解析表单内容
    const uploadData: Record<string, any> = {}
    let fileBuffer: Buffer | null = null
    for (const item of formData) {
      if (item.name === 'file') {
        fileBuffer = item.data
        uploadData.fileName = item.filename
        uploadData.fileType = item.type
      } else {
        uploadData[item.name] = item.data.toString()
      }
    }

    // 可选:将文件保存到服务器
    if (fileBuffer && uploadData.fileName) {
      const savePath = join(process.cwd(), 'public/uploads', uploadData.fileName)
      await writeFile(savePath, fileBuffer)
    }

    return { body: uploadData }
  } catch (error: any) {
    return { error: error.message }
  }
})

3. 调整iUpload接口(可选)

服务端不再接收File对象,可更新接口匹配实际接收的数据:

export interface iUpload {
  name: string;
  type: string;
  fileName?: string;
  fileType?: string;
}

内容的提问来源于stack exchange,提问作者Olanrewaju Ibironke

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 13:40:55