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

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

一、问题背景

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

二、问题解决

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

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

<el-upload
  class="avatar-uploader"
  action="https://jsonplaceholder.typicode.***/posts/"
  :show-file-list="false"
  :on-su***ess="handleAvatarSu***ess"
  :before-upload="beforeAvatarUpload">
  <img v-if="imageUrl" :src="imageUrl" class="avatar">
  <i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>

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

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

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

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

       在这个函数中,我们首先将上传的图片文件进行了回显,然后将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)键值对中的键的命名取决于你后端接收这个文件参数时使用的名字。

       相关代码如下:

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

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

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

const uploadForm = {
    data: {
        plateNumber:this.carManagementData.editCarInfoForm.plateNumber,
        model:this.carManagementData.editCarInfoForm.carType,
        fuel:this.carManagementData.editCarInfoForm.fuel,
        seatNumber:this.carManagementData.editCarInfoForm.seatNumber,
    }
}

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

const jsonStr = JSON.stringify(uploadForm.data);
const blob = new Blob([jsonStr],{
    type: 'application/json'
 });
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注解来接收前端传过来的对象参数,这样就能够成功接收了。具体代码如下:

@PostMapping(value = "/addCar")
public Result addCar(HttpServletRequest request, @RequestParam(value = "file",required = false)MultipartFile multipartFile, @RequestPart AddCarInfoForm addCarInfoForm) {
    if (addCarInfoForm == null)
    {//缺少参数
        throw MyException.MissParamsError();//抛出异常
     }
    carInfoService.addCarService(addCarInfoForm,multipartFile);//调用服务层
    return Result.su***ess();
}

三、总结

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

转载请说明出处内容投诉
CSS教程_站长资源网 » 【前后端】前端向后端传递文件参数并携带其他参数

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买