前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Vue下载Excel模板和导入遇到的问题

Vue下载Excel模板和导入遇到的问题

作者头像
sunonzj
发布2022-06-21 13:25:16
8460
发布2022-06-21 13:25:16
举报
文章被收录于专栏:zjblogzjblog

因为对vue不熟悉,最近踩了很多坑啊。今天这个下载导出Excel的功能搞了半天啊,,,

Vue下载Excel模板

后端代码参考之前写的博客:Java通过Poi的开发Excel导入导出和下载功能

这次使用jfinal的方法,先在根目录下创建downloadExcelModel目录,将模板Excel文件放进去。

代码语言:javascript
复制
String path = getSession().getServletContext().getRealPath("downloadExcelModel");
            File file = new File(path + "/产品导入模板.xlsx");
            System.out.println(path);
            System.out.println(file.exists());
            if (file.exists()) {
                renderFile(file);
                // renderJson(file.getPath());
            } else {
                renderJson("文件不存在");
            }

然后前台接收文件流,这里。。搞了很久,首先就是vue怎么去接收文件流下载文件,之前的直接用a标签或者form提交都不好使了。

经过一番查找,发现有好几种方法做。

可以前台通过一个点击事件请求后台方法,后台返回一个下载路径。vue获取返回的路径直接下载。

代码语言:javascript
复制
<button type="button" id="product-export" @click="downExcel" class="btn btn-outline-hover-info btn-elevate btn-pill"> <i class="fa fa-export"></i> 模板下载 </button>


downExcel:function(){
      this.$http.post(_api.downExcel).then(response => {
        const url = response.data;
        window.location.href = url;
      }).catch(err => {
        _toastr.error(err)
      })
    },

还有就是通过后台返回的文件流下载,vue需要用 new Blob([data])来处理。遇到的问题就是下载下来的一直打不开或者乱码。

155496476843528030695.png
155496476843528030695.png
155496478585245086876.png
155496478585245086876.png
155496480022800081044.png
155496480022800081044.png

需要修改请求成

代码语言:javascript
复制
$http.post(_api.downExcel,{headers:'application/x-download'},{ responseType: 'blob'}) 或者 { responseType: 'arraybuffer'})
const blob = new Blob([response.data], {type: "application/vnd.ms-excel"}

这样就不会乱码了,注意接受的返回值得获取。有两种方式,完整代码:

代码语言:javascript
复制
downExcel:function(){
      this.$http.post(_api.downExcel,{headers:'application/x-download'},{ responseType: 'blob'}).then(response => {
        console.log(response.data);
        const blob = new Blob([response.data], {type: "application/vnd.ms-excel"});
      //第一种
         const fileName = '产品导入模板.xls';
         const elink = document.createElement('a');
         elink.download = fileName;
         elink.style.display = 'none';
         elink.href = URL.createObjectURL(blob);
         document.body.appendChild(elink);
         elink.click();
         URL.revokeObjectURL(elink.href); // 释放URL 对象
         document.body.removeChild(elink);
         //        第二种  
         //  const url = URL.createObjectURL(blob);
          //   window.location.href = url;
          //  window.location.href = response.data;
          
      }).catch(err => {
        _toastr.error(err)
      })
    },
155496481687516088814.png
155496481687516088814.png

Vue导入Excel

后端的话看之前博客,一样的(注意下jfinal的cos包导了没,不然getFile()有问题),主要还是前端的问题,怎么提交文件,之前在搞组件,那样以后可以直接拿来用,后来没搞成,就还是from表单提交了。。。

注意后端可能报下面这个错,换下新的ExcelUtil就好,已更新之前的博客。

代码语言:javascript
复制
: The supplied data appears to be in the Office 2007 XML. You are calling th

原因是: HSSFWorkbook:是操作Excel2003以前(包括2003)的版本,扩展名是.xls  XSSFWorkbook:是操作Excel2007的版本,扩展名是.xlsx

后台还有个多级联查的类型。比如Excel有个字段为地点,表里存的是字典表对应的code。根据Excel里的地点查出对应code,比如Excel中填的是“浙江省杭州市萧山区”因为地点是有多级组成的:(浙江省+杭州市+萧山区)对应的code是(005001+005001002+005001002001)。

这时候就需要先将字典表的所有城市查出来放入一个map中,Map<省市区, 区的code>这样的集合。

思路:根据地点在字典表的父code“005”,查出所有地点List<city>,然后转成一个Map<code, name>集合;

   循环List<city>,循环中获取city的code,因为我字典表存的规则是子节点是在父节点上加三位数表示的。在根据code长度循环,分别获取区、市、省的名称,并组成省市区(例:浙江省杭州市萧山区),code的map。

   最后就是根据Excel中填写的地点名map.get("地点名")获取对应code存入数据库。这样还防止了子节点和父节点有重复名称的影响。

代码

代码语言:javascript
复制
 // 查询字典表所有产品类型的子节点列表
        BasicDictionary basicDictionary = new BasicDictionary().setIsDeleted(false);
        Condition.getInstance(basicDictionary.getCodeFieldName()).equation(Equation.RIGHT_LIKE)
            .value(Var.PRODUCT_CODE.toString()).attachMe(basicDictionary);
        List<BasicDictionary> listDictionary = basicDictionaryService.findList(basicDictionary);
        // 将产品类型列表转化为code:name的map集合
        Map<String, String> dictionaryMap =
            Tools.list2Map(listDictionary, BasicDictionary::getCode, BasicDictionary::getName);
        Map<String, String> codeMap = new HashMap<String, String>();
        // 遍历产品列表将产品类型以 产品类型最低节点到最高节点名字相加(相当于连接完整类型名称):对应code
        listDictionary.stream().forEach(e -> {
            String code = "";
            for (int len = e.getCode().length(); len >= 6; len -= 3) {
                code = dictionaryMap.get(e.getCode().substring(0, len)) + code;
            }
            codeMap.put(code, e.getCode());
        });

导入Excel前端代码

代码语言:javascript
复制
        <form>
          <input type="file" @change="getFile($event)" class="" multiple/>
          <input type="button" value="upload" @click="importExcel($event)" class="btn btn-dark">
        </form>
        
        
    getFile:function(event){
      this.file = event.target.files[0];
      console.log(this.file);
    },
    importExcel:function(event){
      event.preventDefault();
      let formData = new FormData();
      formData.append("file", this.file);
      this.axios.post(_api.importExcel, formData).then(response => {
        _toastr.notification(response.data, true);

      }).catch(err => {
        _toastr.error(err)
      })
    },

后面可能会搞成组件吧,暂时还不太懂。。

根据现在对vue的使用情况,感觉有些地方是很爽,比之前直接写活用框架要方便,但是也有很多不便之处,大都是因为不熟悉的缘故吧。

刚开始用vue还有点排斥,用了会就能发现它的好处了。慢慢来,熟悉了说不定就喜欢用了呢。。

还有vue的列表,表单,等地方踩了很多坑,不过后面再用就知道了,多亏了网上别人的博客,基本都是靠查别人博客或者论坛社区解决的。不得不说要是网上没那么多别人写的,很多问题还真不知道咋解决。。

所以记下自己踩过的坑,还有很重要的。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-04-11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档