axios下载excel踩坑记录(导出Excel总是报格式错误而且乱码)

项目需要,有一个功能是后端生成Excel文件并且写入文件流,前台接收并提示用户导出文件。

看起来是个很简单的功能,网上关于这个功能的解决办法也有很多,基本都差不多,大致如下:

  • 后端:
@RequestMapping(value = "/exportGatherXls", method = RequestMethod.POST)
  public void exportGatherXls(HttpServletResponse response) {
    //导出Excel
    response.setContentType("application/vnd.ms-excel;charset=utf-8");
    String codedFileName = "test";
    OutputStream fOut = null;
    try {
      String newtitle = new String(codedFileName.getBytes("UTF-8"), "ISO8859-1");
      response.setHeader("content-disposition", "attachment;filename=" + newtitle + ".xls");
      Workbook workbook = new HSSFWorkbook();
      //2.创建工作簿
      Sheet sheet = workbook.createSheet();
      //3.创建标题行,测试数据
      Row titlerRow = sheet.createRow(0);
      titlerRow.createCell(0).setCellValue("省");
      titlerRow.createCell(1).setCellValue("市");
      titlerRow.createCell(2).setCellValue("区");
      titlerRow.createCell(3).setCellValue("邮编");
      titlerRow.createCell(4).setCellValue("简码");
       titlerRow.createCell(5).setCellValue("城市编码");
      fOut = response.getOutputStream();
      workbook.write(fOut);
      workbook.close();
    } catch (Exception e) {

    }finally {
      try {
        if (fOut != null) {
          fOut.flush();
          fOut.close();
        }
      } catch (IOException e) {
      }
    }
  }
  • 前端:
axios({
    method: 'post',
    url: url,
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    }
    data: qs.stringify(params, {arrayFormat: 'brackets'}),
    // 这个非常重要!!
    responseType: 'blob'
  }).then(response => {
    let blob = new Blob([response.data], {type: 'application/vnd.ms-excel;charset=utf-8'});
    let downloadElement = document.createElement('a');
    let href = window.URL.createObjectURL(blob); //创建下载的链接
    downloadElement.href = href;
    downloadElement.download = '导出文件.xls'; //下载后文件名
    document.body.appendChild(downloadElement);
    downloadElement.click(); //点击下载
    document.body.removeChild(downloadElement); //下载完成移除元素
    window.URL.revokeObjectURL(href); //释放掉blob对象
  });

基本上就可以实现导出功能了。

但是!我尝试了无数次都遇到了导出的文件打开提示错误并且乱码的问题:

axios下载excel踩坑记录(导出Excel总是报格式错误而且乱码)_第1张图片

强行打开是这个鬼样子:

axios下载excel踩坑记录(导出Excel总是报格式错误而且乱码)_第2张图片

我对照网上的下载文件的代码检查和尝试了很多次都是这个错误,直到查看response的结构发现了这个:

这里的request类型不是原生的XMLHttpRequest,data是字符串类型,按照我们的设置应该是blob类型才对。

字面意思看起来应该是我使用了mockjs所以导致了Request类型被封装,去掉mock引入,正解!

结论:下载文件不要使用mockjs,尽管并没有配置拦截下载的后端地址,但是mock会拦截所有的请求,匹配规则的就使用模拟数据,不匹配的也会使用封装后的request请求后台。

真是一个不容易发现原因的问题,前后花了大半天时间才解决。希望可以帮助到和我遇到一样问题的小伙伴们~

你可能感兴趣的:(前端,vue)