2

I am sending data to a Nuxt 3 server side defineEventHandler. The data is correctly sent to it as a multipart/form content-type. However, I want to get the data in the FormData sent to defineEventHandler but when I use readMultipartFormDat(event) to get the payload, I get undefined. How can I can get the file contents to upload to a 3rd party database that can store MS Excel files by supplying it with a Buffer or Blob or ArrayBuffer of the file contents. Here is how I create the fetch request.

createFormData = (file: File): FileRequest => {
  const headers = new Headers({
    "Content-Type": "multipart/form-data",
    "fileName": file.name,
  }) 
  const formData = new FormData()
  formData.append("userFile", file, file.name);
  const requestData: FileRequest = {
    formData: formData,
    fileHeaders: headers
  }
  return requestData 
}

This is the code that actually sends the code to the server side component

function uploadFile(file: File) {
  const fileRequest =  createFormData(file)
  const url = '/data/file/api/loader' 
        
  try {
    const requestInit: RequestInit = {
      method: 'POST',
      body: fileRequest.formData,
      headers: fileRequest.fileHeaders
    }
    const response = fetch(url, requestInit);
    return {
      status: response.status
    }
  } catch(error) {
    console.log("Error uploading file", error)
  }
}

Finally, the fetch sends data to this component which is responsible for storing the upload file in the proprietary document database.

This is server/api/loader.ts so the fetch url is /data/file/api/loader as NUXT_APP_BASE_URL=/data/file

import { InnoDB } from 'inno-db'
export default defineEventHandler(async (event) => {
  // Do not know how to get the FormData from payload
  const payload = await readBody(event)
            
  const fileName  = getRequestHeader(event, 'fileName')
  const fileType  = getRequestHeader(event, 'fileType')
  const fileTTL  =  getRequestHeader(event, 'fileTTL')

  const dbFileInstance = new InnoDb(
    id: InnoDB.autoGenerate,
    // I need to get the FormData file contents as a Buffer  
    File: Buffer, 
    FileName: fileName,
    Content-Type: fileType,
    TTL: fileTTL
  )
  dbFileInstance.save((doc, err) => {
    // Log and Handle errors
  })
})

I would appreciate if someone can point me to how to obtain the FormData from the payload and convert it to a Buffer object the database contents

Tyler2P
  • 2,324
  • 26
  • 22
  • 31
BreenDeen
  • 623
  • 1
  • 13
  • 42

2 Answers2

2

You can simplify the way your are performing your API call. In the following example I'll be using $fetch which in that case will detect that you're sending a FormData and will automatically add the corresponding header.

So, here's the function to perform your API call.

async function uploadFile(file: File) {
  const formData = new FormData()
  formData.append('file', file)

  const response = await $fetch('/data/file/api/loader', {
    method: 'post',
    body: formData,
  })

  // etc...
}

By doing so, on the server side the readMultipartFormData should work as expected. You can try to get the file on the server side.

export default defineEventHandler(async (event) => {
  const files = await readMultipartFormData(event)

  console.log(files)
})
BghinC
  • 101
  • 1
  • 11
  • 1
    It wasn't working because I was including the content type. Once I removed it it started working. Please see my comments below. – BreenDeen May 08 '23 at 19:06
1

I found the issue. Adding the Content-Type header in the method to create the FormData results in the browser not sending the boundary prefix i.e. boundary=---WebKitxxxxx etc. I modified the creation like so and that worked


               createFormData = (file:File): 
                  FileRequest => {
     
                  const headers = new Headers({
                  'fileName': file.name,
                 }) 
                  const formData = new FormData()
                  formData.append("userFile", file, file.name);
                  const requestData:FileRequest = {
                     formData: formData,
                     fileHeaders: headers
                 }
                   return requestData 
               }


Notice that 'Content-Type': 'multipart/form-data' is not included here.

BreenDeen
  • 623
  • 1
  • 13
  • 42