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

Nuxt3服务器端如何获取FormData文件并转为Buffer存入第三方数据库?

问题解决步骤

前端代码修复

你的前端代码存在两个关键问题,会导致后端无法正确解析FormData:

  1. 手动设置Content-Type: multipart/form-data丢失boundary信息:当fetch的body为FormData时,浏览器会自动生成带boundary的Content-Type头(例如multipart/form-data; boundary=----WebKitFormBoundaryxxx),手动设置会覆盖这个自动生成的头,导致后端无法分割表单数据。
  2. fetch请求未处理异步逻辑:fetch是异步函数,直接读取response.status会拿到Promise对象而非实际状态码。

修改后的前端代码:

createFormData = (file: File): FileRequest => {
  const headers = new Headers({
    // 移除手动设置的Content-Type,交给浏览器自动处理
    "fileName": file.name,
    "fileType": file.type, // 补充文件类型到请求头
    "fileTTL": "3600" // 根据实际需求设置TTL值
  }) 
  const formData = new FormData()
  formData.append("userFile", file, file.name);
  const requestData: FileRequest = {
    formData: formData,
    fileHeaders: headers
  }
  return requestData 
}
async function uploadFile(file: File) { // 改为async函数
  const fileRequest = createFormData(file)
  const url = '/data/file/api/loader' 
        
  try {
    const requestInit: RequestInit = {
      method: 'POST',
      body: fileRequest.formData,
      headers: fileRequest.fileHeaders
    }
    const response = await fetch(url, requestInit); // 添加await处理异步
    return {
      status: response.status
    }
  } catch(error) {
    console.log("Error uploading file", error)
    return { status: 500 }
  }
}

后端代码修复

Nuxt3中处理multipart/form-data需要使用readMultipartFormData而非readBody,同时要注意将文件数据转换为Buffer的方法:

import { InnoDB } from 'inno-db'
export default defineEventHandler(async (event) => {
  // 读取multipart表单数据
  const formData = await readMultipartFormData(event)
  if (!formData) {
    throw createError({ statusCode: 400, statusMessage: '未接收到表单数据' })
  }

  // 定位到表单中的文件项
  const fileItem = formData.find(item => item.name === 'userFile')
  if (!fileItem) {
    throw createError({ statusCode: 400, statusMessage: '表单中未找到文件' })
  }

  // 获取请求头中的参数
  const fileName = getRequestHeader(event, 'fileName') || fileItem.filename
  const fileType = getRequestHeader(event, 'fileType') || fileItem.type
  const fileTTL = getRequestHeader(event, 'fileTTL') || '3600'

  // 将文件的Uint8Array数据转换为Buffer
  const fileBuffer = Buffer.from(fileItem.data)

  // 创建数据库实例(修复原代码的语法错误,属性名需加引号)
  const dbFileInstance = new InnoDB({
    id: InnoDB.autoGenerate,
    File: fileBuffer,
    FileName: fileName,
    'Content-Type': fileType,
    TTL: fileTTL
  })

  // 用Promise封装回调逻辑,避免回调地狱
  try {
    await new Promise((resolve, reject) => {
      dbFileInstance.save((doc, err) => {
        if (err) reject(err)
        else resolve(doc)
      })
    })
    return { status: 200, message: '文件上传成功' }
  } catch (err) {
    console.error('数据库保存失败:', err)
    throw createError({ statusCode: 500, statusMessage: '文件保存到数据库失败' })
  }
})

额外注意事项

  • 配置请求体大小限制:如果上传大文件,需要在nuxt.config.ts中调整请求体大小限制:
    export default defineNuxtConfig({
      server: {
        maxRequestBodySize: '10mb' // 根据实际文件大小调整
      }
    })
    
  • 确认数据库参数要求:如果inno-db的File字段接受Blob或ArrayBuffer类型,可直接使用fileItem.data(Uint8Array可直接转换为这两种类型)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 01:02:52