采用from-data传参后端获取不到参数问题

本文讲述了在使用axios和elementplus的上传组件配合Go后端处理文件上传时遇到的问题,涉及到了MultipartForm和不同参数映射的理解。作者通过实例和源码分析,发现前端传递参数方式导致后端无法识别,最终提供了解决方案并分享了修改后的前端代码和后端Java代码。
摘要由CSDN通过智能技术生成

问题的起因是在项目中编写的一个上传文件的接口中,前端采用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","系统异常");
        }
    }

改完之后测试了一下,确实可以了

  • 33
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值