前几天在使用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/作为一个中转,也可使用其他代理方式)。但是这里的headers的content-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请求