使用el-upload进行文件上传,前后端实现中的大小问题

本文记录了在Vue项目中使用el-upload组件进行文件上传时遇到的前端和后端问题,包括500错误、文件内容为空、文件类型错误等,并详细描述了解决过程和解决方案。通过调整前端FormData的构造方式,以及后端处理请求的不同方法,最终成功实现了文件上传。
部署运行你感兴趣的模型镜像

使用文件上传

平台要用到一个数据库对比功能,需要上传个模板excel,就开始使用element-ui的el-upload组件。

前端实现

照着https://element.eleme.cn/#/zh-CN/component/upload的文档一顿复制修改,因为要传文件和参数,使用formdata形式上传,Content-Type设置为multipart/form-data,实现如下:

  <el-upload
     action="/tank/compare/upload"
     :on-preview="handlePreview"
     :auto-upload="false"
     :multiple="false"
     accept=".xlsx,.xls"
     :on-change="changeFile"
     >
     <el-button size="small" type="primary">上传对比表</el-button>
     <div slot="tip">按模板上传对比表</div>
   </el-upload>
<script>
    changeFile (file) {
      let fd = new FormData()
      fd.append('file', file)
      fd.append('aid', this.selecta)
      fd.append('bid', this.selectb)
      fd.append('fileName', file.name)
      let config = {
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      }
      axios.post('/compare/upload2', fd, config).then(data => {
        if (data.code === 200) {
          this.$message.info('成功上传')
        }
      })
    }

后端实现

后端直接在controller使用MultipartHttpServletRequest获取文件,转换成File保存和读取,实现如下:

    //上传文件
    @RequestMapping(value="upload2",method = RequestMethod.POST)
    public CommonVO upload2(MultipartHttpServletRequest  request){
        MultipartFile file = request.getFile("file");
        CommonVO cVo = new CommonVO();
        SimpleDateFormat sdf = new SimpleDateFormat("/yyyyMMdd/");
        String format = sdf.format(new Date());
        String realPath = request.getServletContext().getRealPath("/upload") + format;
        // 这是个目录
        File folder = new File(realPath);
        if (!folder.exists()) {
            folder.mkdirs();
        }
        String oldName = file.getOriginalFilename();
        String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
//         目录文件
        File tarFile = new File(folder,newName);
        try {
            file.transferTo(tarFile);
        } catch (Exception e) {
            e.printStackTrace();
        }
        CompareObject co = new CompareObject();
        // 获取excel文件内容
        co.init(ExcelReadUtil.getSheetByFile(tarFile));
        cVo.setCode(200);
        return cVo;
    }

第一个问题

前后端实现完成,开始调用,直接报错500,请求也不进入controller方法
java.lang.IllegalStateException: Current request is not of type [org.springframework.web.multipart.MultipartHttpServletRequest]: org.apache.catalina.connector.RequestFacade@3f15fd68
还好,网上碰到该问题的还是挺多,需要在spring增加个配置,以实现spring对multipart/form-data请求直接转换成MultipartHttpServletRequest:

    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="UTF-8" />
        <property name="maxInMemorySize" value="5242880"/>
    </bean>

第二个问题

配置好后,请求成功进入到controller,但是debug发现文件内容为空
在网上查了一通,有各种说法,开始尝试使用第二种后端实现方式,用HttpServletRequest来做转化:

    public CommonVO upload(HttpServletRequest req){
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) req;
        List<MultipartFile> file = multipartRequest.getFiles("file");
        ----其他实现
    }

但是发现还是为空,问题依旧。
继续在网上找寻答案,因为对springmvc的了解有限,只求知道所以然,不求知道之所以然,开始使用第三种后端实现,去掉spring请求转换配置,使用servletUpload组件来读取参数:

  DiskFileItemFactory factoy=new DiskFileItemFactory();
  ServletFileUpload sfu=new ServletFileUpload(factoy);
  try {
      List<FileItem> list = sfu.parseRequest(req);
      for(FileItem fi:list){
          if(fi.isFormField()){
              String s = fi.toString();
          }else{
              String filename = fi.getFieldName();
              tarFile = new File(folder,filename);
              fi.write(tarFile);
          }
      }
  }

成功解析到参数list。

第三个问题?

参数成功解析了,可是文件内容还是获取不到,写出来的文件内容为[object Object]
搜了不少后端问题,都没有相关答案,开始看看是不是前端问题(其实早该想到了);
想到使用postman来调用试试,结果还真的成功写了10K的文件,开始对比postman和浏览器的请求区别,并未发现什么。
继续寻求帮助,找到一个突破口,在stackoverflow有个类似问题,他们也是解析FileItem.isFormField为true,等于说该参数为普通非文件参数,他们给出的答案是需要加上filename,不加默认为普通参数。
有方向是好事情,那么怎么给FormData加上文件名字呢?一个网站说是可以fd.append(‘file’, file, file.name),设置3参数,可是实际运行有js报错:
TypeError: Failed to execute ‘append’ on ‘FormData’: parameter 2 is not of type ‘blob’
前端打印file是什么类型,typeof file,为object,的确是类型错误,继续查找object怎么转file:

var file2 = new File(file, file.name, {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', lastModified: Date.now()})

还是报其他错误;
在各种调试中无意间发现file是object,但是file.raw居然是File类型
在这里插入图片描述
尝试性的用file.raw来传输,

fd.append('file', file.row, file.name)

OK了!!

继续尝试

搞半天原来一直是传错类型了,那么前面说的一定要传filename是否也是问题所在呢,去掉filename调用,也可以!说明问题并不真是少传name引起的,弄巧成拙。
没有真正理解js原理的痛,居然就是一直传错对象引起,过程中也有一些教训,后期一定要多多尝试debug,输出对象来定位问题,不要一味去网上直接寻求答案,可能有,但应该要先有自己的思考!
继续想,之前后端的一二种方法是否可以呢,把去掉的配置加回来,使用MultipartHttpServletRequest解析请求,也是一切正常!这次加个心眼,F12发现请求的内容体也与之前不同:
在这里插入图片描述
前面一直是:
在这里插入图片描述
真相一直就在眼前,可就一直没发现。。。

待了解

那么还剩下一个问题,on-change(file)是官方方法,名字也是file,为什么类型就是object,而file.raw才是真正的File文件呢,raw是个什么鬼,在js中特殊定义吗?
不解,需要看vue原码了(level还不够),如果有大佬刚好在看,可否帮忙解答下,多谢!!

参考文档:
Element Upload上传组件调接口时踩坑
servlet完成form格式下的文件 文本信息上传
SpringMVC中servletFileUpload.parseRequest(request)解析为空获取不到数据问题

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值