Nuxt3如何在server里面发送formData请求

370 阅读1分钟

前几天在使用Nuxt3的时候,当前端发送请求体为FormData时,请求到了Nuxt的server/下时无法解析body中的FormData,最终找到解决方法,特此记录一下

  • 前端代码
<template>
  <div>
    <input type="file" @change="handleChange" />
  </div>
</template>
<script setup>
const handleChange = (e) => {
  const file = e.currentTarget.files[0];
  const formData = new FormData();
  formData.append("file", file);
  formData.append("warn", "警告");
  formData.append("desc", "简介");

  const res = $fetch("/api/upload", {
    method: "post",
    body: formData,
  });
};
</script>

用户点击按钮时发送请求到/api/upload,参数为FormData类型

  • Nuxt/server/下代码

当解析body中的formData是,不可以使用readBody,该方法只能解析application/json类型数据,因此要使用readFormData,获取到的FormData基本和前端传过来的一致(FormData在node>=18.0.0的版本中才能使用),然后就可以将FormData作为body继续传输给后端(Nuxt的server/作为一个中转,也可使用其他代理方式)。但是这里的headerscontent-type不能设置为multipart/form-data(不知道为啥🤔️🤔️),设置了后端就获取不到文件。

import { readFormData } from "h3"
export default defineEventHandler(async event => {
  const body: any = await readFormData(event);
  try {
    const res = await $fetch("http://localhost:8888/file/upload", {
      method: "post",
      body,
      /*headers: {//设置了后端就拿不到文件🤔️🤔️
        "Content-type":"multipart/form-data"
      }*/
    });  
  } catch (e) {
  }
  return {};
});

h3具体处理文档

  • SprintBoot代码 服务端文件上传代码片段(使用minio),后端接受文件类型为MultipartFile
@PostMapping("/upload")  
public R<List<FileDTO>> uploadFile(@RequestParam("file") List<MultipartFile> fileList,  
@RequestParam("desc") List<String> descList,  
@RequestParam("warn") List<String> warnList) throws Exception{  
  
List<String> urlList= new ArrayList<>();  
List<FileDTO> fileDTOList = new ArrayList<>();  
for(int i=0;i<fileList.size();i++){  
MultipartFile file = fileList.get(i);  
String fileType = file.getContentType().substring(0,file.getContentType().indexOf("/"));  
String filename = new FileUniqueName().getFileUniqueName(file.getOriginalFilename());  
  
  
Base64.Encoder eNcoder = Base64.getEncoder();  
byte [] textByte = fileType.getBytes("UTF-8");  
String text = eNcoder.encodeToString(textByte);  
  
fileType = text+"gb";  
MessageDigest md5 = MessageDigest.getInstance("MD5");  
md5.update(fileType.getBytes());  
  
byte[] bytes = md5.digest();  
BigInteger bigInteger = new BigInteger(1,bytes);  
String result = bigInteger.toString(16);  
while (result.length() < 32){  
result ="0" +result;  
}  
fileType = result;  
  
boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(fileType).build());  
if(!isExist){  
minioClient.makeBucket(MakeBucketArgs.builder().bucket(fileType).build());  
String p = "{\"Statement\":[{\"Sid\":\"PublicRead\",\"Action\":[\"s3:GetObject\"],\"Effect\":\"Allow\",\"Principal\":\"*\",\"Resource\":[\"arn:aws:s3:::"+fileType+"/*\"]}],\"Version\":\"2012-10-17\"}";  
minioClient.setBucketPolicy(SetBucketPolicyArgs.builder()  
.bucket(fileType)  
.config(p).build());  
}  
ObjectWriteResponse objectWriteResponse = minioClient.putObject(PutObjectArgs.builder()  
.bucket(fileType)  
.object(filename)  
.contentType(file.getContentType())  
.stream(file.getInputStream(),file.getSize(),-1).build());  
  
  
String desc = i > descList.size()-1 ? "" : descList.get(i);  
String warn = i > warnList.size()-1 ? "" : warnList.get(i);  
  
Upload uploadFile = new Upload();  
uploadFile.setId(new Date().getTime()+"");  
uploadFile.setOriginalname(file.getOriginalFilename());  
uploadFile.setSize(file.getSize()+"");  
uploadFile.setFilename(filename);  
uploadFile.setDescription(desc);  
uploadFile.setWarn(warn);  
uploadFile.setUrl(Host.MINIO_HOST.getHOST()+"/"+fileType+"/"+filename);  
uploadService.uploadFile(uploadFile);  
urlList.add(uploadFile.getUrl());  
  
FileDTO fileDTO = new FileDTO();  
fileDTO.setId(uploadFile.getId());  
fileDTO.setUrl(uploadFile.getUrl());  
fileDTOList.add(fileDTO);  
}  
return R.ok(fileDTOList);  
}

Nuxt3在server/转发FormData请求