saber2.3.5最新版实现“导出excel”显示乱码

======问题已解决,是mock模式导致的问题,关闭mock即可

src/mock中index.js文件中

把const options = {mock: true}; 

修改为:

const options = {mock: false};



一、该问题的重现步骤是什么?

1. 1.9号下载最新的前端2.3.5版本,把之前版本中导出功能迁移过,同时开启2个前端调用最新的2.3版本后台接口,老的版本正常导出数据,新的2.3.5 下载文件无法打开,监控显示乱码 ,请问这新升级的版本和老板本有设置编码格式吗?

2. 通过easypoi实现功能导出:

后台UserController增加了一个导出方法


@RequestMapping(value="/exportexcel",method = RequestMethod.GET)
@GetMapping("/exportexcel")
public void exportExcel(HttpServletResponse response, User user){
   System.out.println(user);
   List<User> userList = userService.list(Condition.getQueryWrapper(user));
   try {
      List<UserVO> userVOList = new ArrayList<UserVO>();
      for(User u : userList){
         UserVO userVO = UserWrapper.build().entityVO(u);
         userVOList.add(userVO);
      }
      ExcelUtils.exportExcel(userVOList,"员工信息表", "员工信息", UserVO.class, "员工信息", response);
   }
   catch (Exception e) {
      e.getMessage();
   }
}




实体类:
@Excel(name = "手机号码",orderNum = "30",width = 20)
private String phone;


3.ExcelUtils实现类:

import cn.afterturn.easypoi.entity.vo.NormalExcelConstants;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.afterturn.easypoi.view.PoiBaseView;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.ui.ModelMap;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;

public class ExcelUtils {
    /**
     * excel 导出
     *
     * @param list           数据
     * @param title          标题
     * @param sheetName      sheet名称
     * @param pojoClass      pojo类型
     * @param fileName       文件名称
     * @param isCreateHeader 是否创建表头
     * @param response
     */
    public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName, boolean isCreateHeader, HttpServletResponse response) throws IOException {
        ExportParams exportParams = new ExportParams(title, sheetName, ExcelType.XSSF);
        exportParams.setCreateHeadRows(isCreateHeader);
        defaultExport(list, pojoClass, fileName, response, exportParams);
    }

    /**
     * excel 导出
     *
     * @param list      数据
     * @param title     标题
     * @param sheetName sheet名称
     * @param pojoClass pojo类型
     * @param fileName  文件名称
     * @param response
     */
    public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName,
                           HttpServletResponse response) throws IOException {
        defaultExport(list, pojoClass, fileName, response, new ExportParams(title, sheetName, ExcelType.XSSF));
    }

    /**
     * excel 导出
     *
     * @param list         数据
     * @param pojoClass    pojo类型
     * @param fileName     文件名称
     * @param response
     * @param exportParams 导出参数
     */
    public static void exportExcel(List<?> list, Class<?> pojoClass, String fileName, ExportParams exportParams, HttpServletResponse response) throws IOException {
        defaultExport(list, pojoClass, fileName, response, exportParams);
    }

    /**
     * excel 导出
     *
     * @param list     数据
     * @param fileName 文件名称
     * @param response
     */
    public static void exportExcel(List<Map<String, Object>> list, String fileName, HttpServletResponse response) throws IOException {
        defaultExport(list, fileName, response);
    }

    /**
     * 默认的 excel 导出
     *
     * @param list         数据
     * @param pojoClass    pojo类型
     * @param fileName     文件名称
     * @param response
     * @param exportParams 导出参数
     */
    private static void defaultExport(List<?> list, Class<?> pojoClass, String fileName, HttpServletResponse response, ExportParams exportParams) throws IOException {
        Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, list);
        downLoadExcel(fileName, response, workbook);
    }

    /**
     * 默认的 excel 导出
     *
     * @param list     数据
     * @param fileName 文件名称
     * @param response
     */
    private static void defaultExport(List<Map<String, Object>> list, String fileName, HttpServletResponse response) throws IOException {
        Workbook workbook = ExcelExportUtil.exportExcel(list, ExcelType.HSSF);
        downLoadExcel(fileName, response, workbook);
    }

    /**
     * 下载
     *
     * @param fileName 文件名称
     * @param response
     * @param workbook excel数据
     */
    private static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) throws IOException {
        try {
            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-Type", "application/vnd.ms-excel");
//       response.setHeader("content-Type", "application/octet-stream");
         String excelFileName=URLEncoder.encode(fileName + "." + ExcelTypeEnum.XLSX.getValue(), "UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + excelFileName);
         response.setHeader("responseType","blob");
            OutputStream output = response.getOutputStream();
         BufferedOutputStream bufferedOutPut = new BufferedOutputStream(output);
         workbook.write(bufferedOutPut);
         bufferedOutPut.flush();
         bufferedOutPut.close();
         output.close();
            //workbook.write(response.getOutputStream());
        } catch (Exception e) {
            throw new IOException(e.getMessage());
        }
    }

    /**
     * excel 导入
     *
     * @param filePath   excel文件路径
     * @param titleRows  标题行
     * @param headerRows 表头行
     * @param pojoClass  pojo类型
     * @param <T>
     * @return
     */
    public static <T> List<T> importExcel(String filePath, Integer titleRows, Integer headerRows, Class<T> pojoClass) throws IOException {
        if (StringUtils.isBlank(filePath)) {
            return null;
        }
        ImportParams params = new ImportParams();
        params.setTitleRows(titleRows);
        params.setHeadRows(headerRows);
        params.setNeedSave(true);
        //params.setSaveUrl("/excel/");
        try {
            return ExcelImportUtil.importExcel(new File(filePath), pojoClass, params);
        } catch (NoSuchElementException e) {
            throw new IOException("模板不能为空");
        } catch (Exception e) {
            throw new IOException(e.getMessage());
        }
    }

    /**
     * excel 导入
     *
     * @param file      excel文件
     * @param pojoClass pojo类型
     * @param <T>
     * @return
     */
    public static <T> List<T> importExcel(MultipartFile file, Class<T> pojoClass) throws IOException {
        return importExcel(file, 1, 1, pojoClass);
    }

    /**
     * excel 导入
     *
     * @param file       excel文件
     * @param titleRows  标题行
     * @param headerRows 表头行
     * @param pojoClass  pojo类型
     * @param <T>
     * @return
     */
    public static <T> List<T> importExcel(MultipartFile file, Integer titleRows, Integer headerRows, Class<T> pojoClass) throws IOException {
        return importExcel(file, titleRows, headerRows, false, pojoClass);
    }

    /**
     * excel 导入
     *
     * @param file       上传的文件
     * @param titleRows  标题行
     * @param headerRows 表头行
     * @param needVerfiy 是否检验excel内容
     * @param pojoClass  pojo类型
     * @param <T>
     * @return
     */
    public static <T> List<T> importExcel(MultipartFile file, Integer titleRows, Integer headerRows, boolean needVerfiy, Class<T> pojoClass) throws IOException {
        if (file == null) {
            return null;
        }
        try {
            return importExcel(file.getInputStream(), titleRows, headerRows, needVerfiy, pojoClass);
        } catch (Exception e) {
            throw new IOException(e.getMessage());
        }
    }

    /**
     * excel 导入
     *
     * @param inputStream 文件输入流
     * @param titleRows   标题行
     * @param headerRows  表头行
     * @param needVerfiy  是否检验excel内容
     * @param pojoClass   pojo类型
     * @param <T>
     * @return
     */
    public static <T> List<T> importExcel(InputStream inputStream, Integer titleRows, Integer headerRows, boolean needVerfiy, Class<T> pojoClass) throws IOException {
        if (inputStream == null) {
            return null;
        }
        ImportParams params = new ImportParams();
        params.setTitleRows(titleRows);
        params.setHeadRows(headerRows);
        params.setSaveUrl("/excel/");
        params.setNeedSave(true);
        //params.setNeedVerfiy(needVerfiy);
        params.setNeedVerify(needVerfiy);
        try {
            return ExcelImportUtil.importExcel(inputStream, pojoClass, params);
        } catch (NoSuchElementException e) {
            throw new IOException("excel文件不能为空");
        } catch (Exception e) {
            throw new IOException(e.getMessage());
        }
    }

   public static void downloadByPoiBaseView(List<?> list,Class<?> pojoClass, HttpServletRequest request,
                             HttpServletResponse response) {
       ModelMap map = new ModelMap();
      ExportParams params = new ExportParams("员工资料", "员工资料", ExcelType.XSSF);
      //params.setFreezeCol(2);
      map.put(NormalExcelConstants.DATA_LIST, list);
      map.put(NormalExcelConstants.CLASS, pojoClass);
      map.put(NormalExcelConstants.PARAMS, params);
      PoiBaseView.render(map, request, response, NormalExcelConstants.EASYPOI_EXCEL_VIEW);
   }

    /**
     * Excel 类型枚举
     */
    enum ExcelTypeEnum {
        XLS("xls"), XLSX("xlsx");
        private String value;

        ExcelTypeEnum(String value) {
            this.value = value;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }
    }
}

4、前端VUE代码如下:

<el-button type="primary"
                   size="small"
                   plain
                   
                   icon="el-icon-download"
                   @click="handleDownLoad">导出
        </el-button>
<el-button type="primary"
                   size="small"
                   plain
                   
                   icon="el-icon-download"
                   @click="handleDownLoad">导出
        </el-button>

        
downloadfile(res) {
          console.log('下载文件函数开始');
          console.log(res);
          var blob=new Blob([res.data]);
          var contentDisposition = res.headers['content-disposition']; //从response的headers中获取filename, 后端response.setHeader("Content-disposition", "attachment; filename=xxxx.docx") 设置的文件名;
          var patt = new RegExp("filename=([^;]+\\.[^\\.;]+);*");
          var result = patt.exec(contentDisposition);
          var filename = result[1];
           
          var downloadElement = document.createElement('a');
          var href = window.URL.createObjectURL(blob); //创建下载的链接
          console.log('href--->'+href);
          var reg = /^["](.*)["]$/g;
          downloadElement.style.display = 'none';
          downloadElement.href = href;
          downloadElement.download = decodeURI(filename.replace(reg,"$1")); //下载后文件名
          document.body.appendChild(downloadElement);
          downloadElement.click(); //点击下载
          document.body.removeChild(downloadElement); //下载完成移除元素
          window.URL.revokeObjectURL(href); //释放掉blob对象
            
        },

      handleDownLoad(params = {}) {
        this.$confirm("确定将选择数据导出成EXCEL文件?", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        })
          .then(() => {
            return userDownLoad(Object.assign(params, this.query)).then((res)=>{
              console.log('回调开始............'+res);
              this.downloadfile(res);
            });
          }).catch(() => {
            console.log('取消下载............');
          });  
      },


调用js方法:

export const userDownLoad = (params) => {
  return request({
    url: '/api/blade-user/exportexcel',
    method: 'get',
    params: {
      ...params,
    },
    responseType: 'blob'
    
  })
}



二、你期待的结果是什么?实际看到的又是什么?

期望显示如下图:

image.png

实际看到结果:

image.png



三、你正在使用的是什么产品,什么版本?在什么操作系统上?

正在使用最新版本:企业版2.3,saber:2.3.5;操作系统:window10


四、请提供详细的错误堆栈信息,这很重要。


错误信息如上图展示实际看到结果



五、若有更多详细信息,请在下面提供。





1条回答
  • ======问题已解决,是mock模式导致的问题,关闭mock即可

    src/mock中index.js文件中

    把const options = {mock: true}; 

    修改为:

    const options = {mock: false};


    0 讨论(0)
提交回复