2021-04-04利用el-upload+formData传图片踩坑记录

利用formData上传文件遇到的错误及解决方案
真的吐了!!!!!!!!!!!!!!!!!!!!
一个bug改了要一个周!!!!!!

问题描述

啥都感觉没问题,却出现了问题。前端el-upload+formData传文件,后端用multipartFile解析文件,但是收到的图片数组为null!!!!!!!!!

踩坑记录

el-upload图片回显

  1. 直接将处理on-change事件函数中的file加入到fileList数组,但是这样不利于处理数据
handleChange(file, fileList) {
	this.form.file.push(file);
}

2.构造file-list中元素,将其push进file-list数组
在这里插入图片描述

handleChange(file, fileList) {
  	//查阅element-plus文档,发现file-list数组中元素需要满足的对象格式为{name:'xxx',url:'xxxx'}
  let reader = new FileReader();
  reader.readAsDataURL(file.raw);
  reader.onload = (e) => {
    this.form.file.push({ name: file.raw.name, url: e.target.result });
  }
  this.file.push(file.raw);
  fileList = this.form.file;
  }

文件传输格式

  1. 前端发送请求时,请求头需要设置成如下
    且不要再次序列化!!!!!!!!!!!!!!
 header:{
 	'Content-Type': 'multipart/form-data;boundary=<calculated when request is sent>'
 }
  1. 后端处理请求时,需要用multipartFile解析图像文件

默认提交

  1. 默认submit,数据以formData的形式发送给后端
    formData中的键值对{key:value}中的key是表单元素中的name值,value是表单属性中的value值(vue中可以为v-model绑定的值)

  2. 表单外的附带data如何随着表单一起默认提交(如不用在表单中填写的user)
    解决方案:附带数据可以放在一个隐藏的input中,submit时跟着一起提交

<el-input name="user" v-model="user" v-show="false"/>
  1. el-upload组件的name默认为file,前后端接口需对应
    在这里插入图片描述

  2. 默认submit执行后会刷新并跳转页面,没有办法调试
    解决方案:用iframe接收跳转的页面,使得原页面只刷新不跳转

	<el-form  
		ref="form" 
		:model="form" 
		label-width="80px" 
		enctype="multipart/form-data"
		method='post'
		action='接口的url'
		target='myFrame'
		>
	</el-form>
	
	<!-- 接受跳转的iframe -->
	<iframe name='myFrame' style='display:none;'></iframe>
  1. 默认submit无回调函数
    解决方案:自定义submit方法,如下文

自定义提交

  1. formData传输格式后端无法用multipartFile解析
  • 发现的契机
    1.起初我是直接把handleChange(file, fileList) 中的file加入文件数组this.form.file中,查看发出去的请求时,发现formData中的文件数组的类型是[object Object]
    于是我打印this.form.file数组发现这是一个proxy数组,真正的文件在proxy.raw中,也就是说真正的文件是file.raw;
    2.接着我就试着将handleChange(file, fileList) 中file.raw的File数组append进formData发送给后端,此时请求中文件数组的类型变成了[object File]。我真的以为没问题了,但是后端仍然解析不了[苦涩.jpg]
    3.自定义提交不行了,只能再试试表单默认submit。当我试了很多次终于用iframe接收跳转的页面,解决了原页面总跳转无法调试的问题时,我看到了默认submit发出的请求中文件数组的格式是(binary)。
    4.我终于搞懂了原因,我应该把文件以(binary)的形式传给后端解析。

  • 疑惑:为什么formData.append(‘file’,文件数组)之后不是binary形式呢?
    (此间我们做了无数尝试,用fileReader读文件转成Blob,binaryString…都失败了)

  • 解决:直接向formData中添加文件数组,文件不能被分转成(binary),只有每次添加一个文件时该文件才会被转成(binary)传输给后端。
    故多次向formData中同一个键名下添加文件即可
    https://blog.csdn.net/weixin_43249665/article/details/100084637

Final解决方案

html

<el-form ref="form" :model="form" label-width="80px" enctype="multipart/form-data" >
          </el-form-item>
            <el-input name="user" v-model="user" v-show="false"/>
          </el-form-item>
          <el-form-item label="上传图片">
            <el-upload
              list-type="picture-card"
              action="#"
              :limit="9"
              :on-change="handleChange"
              :on-remove="handleRemove"
              :on-exceed="handleExceed"
              :auto-upload="false"
              :multiple="false"
              :file-list="form.file"
              accept="image/png,image/gif,image/jpg,image/jpeg"
            >
              <i class="el-icon-plus"></i>
            </el-upload>
          </el-form-item>
          <div style="width: fit-content; margin: 0 auto 20px">
            <el-button type="primary" @click="handleSubmit()">提交</el-button>
            <el-button @click="dialogVisible = false">取消</el-button>
          </div>
        </el-form>

data

form:{
	user;
	file:[];//保存fileList
}
file[];//

javascript

	handleChange(file, fileList) {
      	//查阅element-plus文档,发现file-list数组中元素需要满足的对象格式为{name:'xxx',url:'xxxx'}
      let reader = new FileReader();
      reader.readAsDataURL(file.raw);
      reader.onload = (e) => {
        this.form.file.push({ name: file.raw.name, url: e.target.result });
      }
      this.file.push(file.raw);
      fileList = this.form.file;
    },
    onCancel() {//取消
      if (confirm("该操作将放弃所有表单内容。确定取消填写吗?")) close();
    },
    handleRemove(file) {
      // 1.从filelist数组中,找到图片对应的索引值
      const i = this.form.files.findIndex(x => x.name === file.name)
      // 2.调用splice方法,移除图片信息
      this.form.files.splice(i, 1);
      const j = this.files.findIndex(x => x.name === file.name)
      this.files.splice(j, 1);
    },
    handleExceed() {
      this.$message(
        {
          message: '图片数不能超过9张',
          type: 'warning'
        }
      )
    },
    handleSubmit() {
        let formData = new FormData();
        for (let i = 0; i < this.file.length; i++) {
          formData.append('file', this.file[i]);
        }
        formData.append('user', this.user);
        this.axios({
          url: '······',
          method: 'post',
          data: {
            formData
          },
          headers: {
            'Content-Type': 'multipart/form-data;boundary=<calculated when request is sent>'
          }
        }).then(
          (res) => {}
          },
          function (err) {
            console.log(err)
          }

ps:在此特别感谢后端调试的朋友们还有帮我改前端代码的学长。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值