您现在的位置是:首页 > 技术教程 正文

【前后端】前端向后端传递文件参数并携带其他参数

admin 阅读: 2024-03-28
后台-插件-广告管理-内容页头部广告(手机)

一、问题背景

       最近在进行某实训,我们的选题涉及到了上传文件的问题,并且在上传文件的同时还要携带其他相关的参数。以我们所做的系统为例:某公司购入一台新车,该车在录入系统时,我们需要向后端上传车辆的图片,同时还需要传递车牌号、车型、座位数这些参数。那么我们如何将文件参数以及其他参数一同传递给后端。经过查阅,作者找到了一种解决办法。

二、问题解决

1.前端如何将用户上传的图片作为参数传递给后端?

       此处我使用的是ElementUI中的上传文件组件Upload,该组件的原始代码如下:

  1. <el-upload
  2. class="avatar-uploader"
  3. action="https://jsonplaceholder.typicode.com/posts/"
  4. :show-file-list="false"
  5. :on-success="handleAvatarSuccess"
  6. :before-upload="beforeAvatarUpload">
  7. <img v-if="imageUrl" :src="imageUrl" class="avatar">
  8. <i v-else class="el-icon-plus avatar-uploader-icon"></i>
  9. </el-upload>

       可以看到这其中有一些事件处理函数,如on-success、before-upload,而我这里没有使用这些函数,而是在其中添加了一个on-change的事件处理函数,这个函数会在用户选择文件或上传文件时被调用,传递相关参数和数据,允许你在处理上传文件的过程中执行一些自定义逻辑。我为其绑定了一个名为handleAddCarChange的函数,修改后的Upload组件代码如下:

  1. <el-upload
  2. :show-file-list="false"
  3. :on-change = "handleAddCarChange"//on-change事件处理函数
  4. :auto-upload="false"
  5. <img v-if="carManagementData.addCarInfoForm.photoPath"
  6. :src="carManagementData.addCarInfoForm.photoPath"
  7. :fit="scale-down" style="width:200px;height:200px;">
  8. <i v-else class="el-icon-plus avatar-uploader-icon" ></i>
  9. </el-upload>

       当我们上传文件后,就会触发其中的handleAddCarChange函数,在handleAddCarChange函数的参数列表中,我们添加一个file参数,这个参数就是我们上传文件后的文件参数。handleAddCa rChange函数如下:

  1. handleAddCarChange(file) {
  2. this.carManagementData.addCarInfoForm.photoPath = URL.createObjectURL(file.raw);//赋值图片的url,用于图片回显功能
  3. this.carManagementData.addCarInfoForm.photoFile = file;//file赋值给我们之前定义的某一个对象
  4. return true;
  5. }

       在这个函数中,我们首先将上传的图片文件进行了回显,然后将file赋值给我们之前已经定义过的一个变量,这样我们就获得了这个文件参数,后续就可以将file作为参数传递给后端。 

2.前端以什么形式将文件参数传递给后端?

       以Axios为例,如果我们使用一般的对象或者参数形式是无法实现文件传递的,必须使用FormData的形式来实现。FormData 是一个用于在 JavaScript 中创建和管理表单数据的 API。它提供了一种方便的方式来构建、序列化和发送包含文件和键值对的表单数据。使用 FormData,我们可以通过一些内置方法来添加键值对或文件数据,最终将整个FormData传递给后端。

       在上一节中,我们已经得到了文件参数file,这里我们首先判断file是否为空,如果不为空,则将this.file.raw添加到formdata中,并将键命名为file。这里有几点需要注意:

(1)一定要使用this.xxx。这是易错点。

(2)一定要使用file.raw,因为file.raw中才是真正的文件参数。

(3)键值对中的键的命名取决于你后端接收这个文件参数时使用的名字。

       相关代码如下:

  1. let formdata = new FormData();
  2. if(this.carManagementData.editCarInfoForm.photoFile != null){
  3. formdata.append("file", this.file.raw);
  4. }

        如果我们还需要传递其他参数怎么办?

        为了方便传参以及后端接收参数,我将其他参数封装成一个对象。首先创建一个新对象,将我们需要像后端传递的参数都放在这个对象中。例如:

  1. const uploadForm = {
  2. data: {
  3. plateNumber:this.carManagementData.editCarInfoForm.plateNumber,
  4. model:this.carManagementData.editCarInfoForm.carType,
  5. fuel:this.carManagementData.editCarInfoForm.fuel,
  6. seatNumber:this.carManagementData.editCarInfoForm.seatNumber,
  7. }
  8. }

       这里我把我需要传给后端的参数都放在了uploadForm这个对象中了。但是现在,我们不能直接将此对象放在FormData中,而是先需要进行一番如下的转换,然后再将其添加到前面的formdata中:

  1. const jsonStr = JSON.stringify(uploadForm.data);
  2. const blob = new Blob([jsonStr],{
  3. type: 'application/json'
  4. });
  5. formdata.append("addCarInfoForm",blob);

       首先,通过 JSON.stringify(uploadForm.data) 将 uploadForm.data 这个 JSON 对象转换为 JSON 字符串。这个 JSON 字符串表示了一个包含表单数据的对象。

       然后,通过 new Blob([jsonStr], { type: 'application/json' }) 创建一个 Blob 对象。Blob 是二进制数据的容器,它可以包含不同类型的数据,并且通过设置 type 属性指定了这个 Blob 对象的 MIME 类型,这里类型为 application/json。

       最后,通过 formdata.append("addCarInfoForm", blob) 将这个 Blob 对象添加到 FormData 中。

完成上述步骤之后,我们就可以使用Axios发送请求了,如下图所示:

 3.后端如何来接收?

       后端可以使用@RequestParam注解来接收文件参数。但是,如果我们使用@RequestBody注解来接收我们传递的对象参数时,发现其传过来的值输出后都为null,但是我们验证之后发现前端确实成功传递了这个对象参数。因此,这里我们要使用@RequestPart注解来接收前端传过来的对象参数,这样就能够成功接收了。具体代码如下:

  1. @PostMapping(value = "/addCar")
  2. public Result addCar(HttpServletRequest request, @RequestParam(value = "file",required = false)MultipartFile multipartFile, @RequestPart AddCarInfoForm addCarInfoForm) {
  3. if (addCarInfoForm == null)
  4. {//缺少参数
  5. throw MyException.MissParamsError();//抛出异常
  6. }
  7. carInfoService.addCarService(addCarInfoForm,multipartFile);//调用服务层
  8. return Result.success();
  9. }

三、总结

      在实训期间,我也是被这个问题困扰了一段时间,希望以上解决方案能够帮到大家,当然,如果有更不错的方法,也请批评指正!

标签:
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

在线投稿:投稿 站长QQ:1888636

后台-插件-广告管理-内容页尾部广告(手机)
关注我们

扫一扫关注我们,了解最新精彩内容

搜索