2024-04-28-采用from-data传参后端获取不到参数问题
目录
采用from-data传参后端获取不到参数问题
问题的起因是在项目中编写的一个上传文件的接口中,前端采用axios+elementplus的上传组件,后端采用go
代码如下
<el-upload
ref="upload"
name="file"
:http-request="handleRequest"
:limit="1"
:auto-upload="false"
>
<template #trigger>
<el-button type="primary">选择文件</el-button>
</template>
<el-button class="ml-3" type="success" @click="submitUpload">
上传
</el-button>
</el-upload>
function handleRequest (e) {
const fd = new FileReader()
fd.readAsDataURL(e.file)
// 将文件转化为base64格式传入后端
fd.onload = () => {
axios .post('http://127.0.0.1:8989/upload', {
imgUrl: fd.result,
}) .then((res) => {
imageUrl.value = res.data.data
})
}
// 上传blob格式
axios.post('http://127.0.0.1:8989/upload', {
imgUrl: URL.createObjectURL(e.file),
}).then((res) => {
imageUrl.value = res.data.data
})
}
func UploadFile(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
http.Error(w, "Only POST requests are allowed.", http.StatusMethodNotAllowed)
return
}
// 解析多媒体表单
err := r.ParseMultipartForm(10 << 20) // 最大文件大小为10MB
if err != nil {
http.Error(w, "Failed to parse multipart form.", http.StatusInternalServerError)
return
}
// 获取表单中的文件
file, _, err := r.FormFile("file")
if err != nil {
http.Error(w, "Failed to retrieve file from form.", http.StatusInternalServerError)
return
}
defer file.Close()
//创建新文件保存文件
dst, err := os.Create("aliyunOSS/happy001.png")
if err != nil {
http.Error(w, "Failed to create destination file.", http.StatusInternalServerError)
return
}
defer dst.Close()
// 将上传的图片数据复制到文件中
_, err = io.Copy(dst, file)
if err != nil {
http.Error(w, "Failed to copy file contents.", http.StatusInternalServerError)
return
}
// 告知客户端图片已成功上传
fmt.Fprintf(w, "File successfully uploaded as %s", "happy.png")
}
开始用apifox测试的时侯一切正常,后面前端测试一直报错Failed to retrieve file from form.没有这个参数,再次用apifox测试也能上传,很奇怪.
期初以为是后端不接收blob格式的传递,就又测试了使用base64还使不行,查看网络请求发现是是带有参数的,但是就是反应没有file这个参数在后端答应file参数发现一直是空的
后面在调试的时侯发现,在请求结构体里面的,对参数的保存是有两个map的
可以发现,在mutilpart-data的请求中回有两种map,一种用于保存字符串类型的值,一种用于保存文件类型的值,由于base64码和blob其实都是以字符串型式传递的
查看源码发现,r.FormFile方法只在File类型的map中查找
if r.MultipartForm != nil && r.MultipartForm.File != nil {
if fhs := r.MultipartForm.File[key]; len(fhs) > 0 {
f, err := fhs[0].Open()
return f, fhs[0], err
}
}
因此就找不到存在Value中的参数了
解决的办法有两种
第一种,把后端读取的方式换一下,从Value里面也遍历一下
第二种,把前端传参的内容改成文件
用哪种可以根据自己的项目情况考虑,我采用的是第二种,原因是后端不是我写的,
贴一下改的前端代码
function handleRequest (e) {
const formData = new FormData();
formData.append('file', e.file);
axios.post('http://127.0.0.1:8989/upload',formData).then(res=>{
if(res.data.code==200){
ruleForm.image=res.data.data
}
})
}
//e.file就是文件本身
另外实际的后端是队友采用java编写的,也贴一下吧
@PostMapping("/upload")
@ApiOperation("文件上传")
public Result<String> upload(@RequestParam("file") MultipartFile file){
if(file == null){
throw new CustomException("-2","传过来的file文件为空!");
}
try {
//原始文件名
String originalFilename = file.getOriginalFilename();
//截取原始文件名的后缀
String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
//构造新文件名称
String objectName = UUID.randomUUID().toString() + extension;
//文件的请求路径
String filePath = aliOssUtil.upload(file.getBytes(), objectName);
return Result.success(filePath);
} catch (IOException e) {
return Result.error("-1","系统异常");
}
}
改完之后测试了一下,确实可以了
68747470733a2f2f626c6f:672e6373646e2e6e65742f323330315f37373034373835392f:61727469636c652f64657461696c732f313338323838303131