How do I process form data for a file upload as FormData on the server side of a Nuxt 3 handler application

huangapple go评论52阅读模式
英文:

How do I process form data for a file upload as FormData on the server side of a Nuxt 3 handler application

问题

Sure, here's the translation of your code:

我正在向一个 Nuxt 3 服务器端的 `defineEventHandler` 发送数据数据已正确以 `multipart/form` 的内容类型发送到它但是我想在 `FormData` 中获取发送到 `defineEventHandler` 的数据但当我使用 `readMultipartFormData(event)` 来获取负载时我得到了 undefined我如何才能获取文件内容以供给第三方数据库该数据库可以存储 MS Excel 文件并提供 `Buffer``Blob`  `ArrayBuffer` 的文件内容以下是我创建 fetch 请求的方式

这是实际将代码发送到服务器端组件的代码

```javascript
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)
  }
}

最后,fetch 发送数据到这个组件,该组件负责将上传的文件存储在专有文档数据库中。

这是 server/api/loader.ts,因此 fetch URL 是 /data/file/api/loader,因为 NUXT_APP_BASE_URL=/data/file

import { InnoDB } from 'inno-db';
export default defineEventHandler(async (event) => {
  // 不知道如何从负载中获取 FormData
  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,
    // 我需要将 FormData 文件内容作为 Buffer 获取
    File: Buffer, 
    FileName: fileName,
    ContentType: fileType,
    TTL: fileTTL
  });
  dbFileInstance.save((doc, err) => {
    // 记录和处理错误
  });
});

如果有人能指导我如何从负载中获取 FormData 并将其转换为数据库内容的 Buffer 对象,我将不胜感激。


<details>
<summary>英文:</summary>

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.


```javascript
createFormData = (file: File): FileRequest =&gt; {
  const headers = new Headers({
    &quot;Content-Type&quot;: &quot;multipart/form-data&quot;,
    &quot;fileName&quot;: file.name,
  }) 
  const formData = new FormData()
  formData.append(&quot;userFile&quot;, 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 = &#39;/data/file/api/loader&#39; 
        
  try {
    const requestInit: RequestInit = {
      method: &#39;POST&#39;,
      body: fileRequest.formData,
      headers: fileRequest.fileHeaders
    }
    const response = fetch(url, requestInit);
    return {
      status: response.status
    }
  } catch(error) {
    console.log(&quot;Error uploading file&quot;, 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 &#39;inno-db&#39;
export default defineEventHandler(async (event) =&gt; {
  // Do not know how to get the FormData from payload
  const payload = await readBody(event)
            
  const fileName  = getRequestHeader(event, &#39;fileName&#39;)
  const fileType  = getRequestHeader(event, &#39;fileType&#39;)
  const fileTTL  =  getRequestHeader(event, &#39;fileTTL&#39;)

  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) =&gt; {
    // 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

答案1

得分: 2

你可以简化你的API调用方式。在以下示例中,我将使用$fetch,在这种情况下,它将检测到你正在发送FormData,并自动添加相应的标头。

所以,这是执行你的API调用的函数。

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,
  })

  // 等等...
}

通过这样做,服务器端的readMultipartFormData应该按预期工作。你可以尝试在服务器端获取文件。

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

  console.log(files)
})
英文:

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(&#39;file&#39;, file)

  const response = await $fetch(&#39;/data/file/api/loader&#39;, {
    method: &#39;post&#39;,
    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) =&gt; {
  const files = await readMultipartFormData(event)

  console.log(files)
})

答案2

得分: 1

我发现了问题。在创建 FormData 的方法中添加 Content-Type 头部会导致浏览器不发送边界前缀,即 boundary=---WebKitxxxxx 等。我修改了创建方式,如下所示,这样可以正常工作:

createFormData = (file: File): 
    FileRequest =&gt; {

    const headers = new Headers({
        &#39;fileName&#39;: file.name,
    }) 
    const formData = new FormData()
    formData.append(&quot;userFile&quot;, file, file.name);
    const requestData: FileRequest = {
        formData: formData,
        fileHeaders: headers
    }
    return requestData 
}

请注意,这里没有包括 'Content-Type': 'multipart/form-data'。

英文:

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 =&gt; {
     
                  const headers = new Headers({
                  &#39;fileName&#39;: file.name,
                 }) 
                  const formData = new FormData()
                  formData.append(&quot;userFile&quot;, file, file.name);
                  const requestData:FileRequest = {
                     formData: formData,
                     fileHeaders: headers
                 }
                   return requestData 
               }


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

huangapple
  • 本文由 发表于 2023年5月7日 09:40:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/76191883.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定