EasyExcel文件导出错误解决

在项目中使用EasyExcel进行Excel导出时,遇到在开发环境正常,但部署到内网测试服务器后导出失败的问题。错误表现为前端收到“下载文件失败”的json文件。经过排查,发现是由于open JDK的字体不全导致。解决方案包括尝试使用过时的代码,或者升级到Oracle JDK。若对版本无特殊要求,低版本xls文件格式也可满足需求。

EasyExcel文件导出错误解决

最近在做一个项目,有将记录导出Excle的需求,采用了阿里的EasyExcel工具,导出功能学习很快,很快参考网站上的代码和官网上资料搞定,并且开发环境(windows)使用非常正常,但是上传到内网测试服务器后,导出总是从异常处退回,服务器端也没有什么信息,这个坑费了和2天时间,特记录下来与大家共享。

一、 先上代码

服务器站代码如下,这段代码使用官网代码一致,只是修改了数据:

 List<QuarantineExport> quarantineExports = employeeService.quarantineExportData(company, department, selectCodeColor, selectQuarState);
        String fileName = URLEncoder.encode("健康码统计信息.xls", "UTF-8");
           try {
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("健康码统计信息", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            // 这里需要设置不关闭流
            EasyExcel.write(response.getOutputStream(), QuarantineExport.class)
                    .autoCloseStream(Boolean.FALSE)
                    .sheet("隔离信息")
                    .doWrite(employeeService.quarantineExportData(company, department,selectCodeColor,selectQuarState));
        } catch (Exception e) {
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            Map<String, String> map = new HashMap<String, String>();
            map.put("status", "failure");
            map.put("message", "下载文件失败" + e.getMessage());
            response.getWriter().println(JSON.toJSONString(map));
        }

前端代码,我有两种模式调整,一种是用按钮直接调URL简单调用,另一种是用ajax和jqery组合复杂条件调用,代码如下。

 var department = $('#departmentList').val();
    var selectCodeColor = $('#selectCodeColor').val();
    var selectQuarState = $('#selectQuarState').val();
    var url = "/statListExport?department="+department+"&selectCodeColor="+selectCodeColor+"&selectQuarState="+selectQuarState;
 $.ajax({
        type: "get",
        async: true,
        url: url,
        contentType: "application/vnd.ms-excel",
        success: function (data) {
            console.log(data);
        },
        error: function (errorMsg) {
            //请求失败时执行该函数
           alert("导出失败!");
        }
    })

二、错误现象

在开发环境使用非常正常,没有任何问题,上传到测试环境服务器不能导出文件,总是产生一个 “下载文件失败” 的json文件,查了很多资料都没有找到方法。
首先,从前端分析错误,这时从前端控制台上发现有一个警告信息,
Resource interpreted as Document but transferred with MIME type application/msexcel:
以为是后台传输正常,到测试服务器环境后这个原因导致的,在这个问题上搞了我一整天,按了4种前端接受后台文件方法,代码贴出来,给大家分享一下。

//这3条是从表单取查询条件
   var department = $('#departmentList').val();
    var selectCodeColor = $('#selectCodeColor').val();
    var selectQuarState = $('#selectQuarState').val();
//w合成后台GET数据的URL,这儿把参数合在一起了,也可以用dataForm或json字符串
    var url = "/statListExport?department="+department+"&selectCodeColor="+selectCodeColor+"&selectQuarState="+selectQuarState;
//方法一:
    var xhr = new XMLHttpRequest();
    xhr.open('Get', url, true);
    xhr.responseType = "blob";    // 返回类型blob
    xhr.onload = function () {
        if (this.status === 200) {
            var blob = this.response;
            var reader = new FileReader();
            reader.readAsDataURL(blob);    // 转换为base64,可以直接放入a表情href
            reader.onload = function (e) {
                var a = document.createElement('a');
                a.download = '健康码统计信息.xlsx';//下载文件名
                a.href = e.target.result;
                $("body").append(a);    // 修复firefox中无法触发click
                a.click();
                $(a).remove();
            }
        }
    };
    // 发送ajax请求

    xhr.send()
//方法二:
        var a = document.createElement('a');
        a.setAttribute("href",url);
        a.click();
        document.body.removeChild(a);*/
//方法三
    var iframe = document.createElement('iframe');
    iframe.id = "IFRAMEID";
    iframe.style.display = 'none';
    document.body.appendChild(iframe);
    iframe.src = url;
    iframe.addEventListener("load", function () {
        console.log("FILE LOAD DONE.. Download should start now");
    });
 //方法四:
    $.ajax({
        type: "get",
        async: true,
        url: url,
        contentType: "application/vnd.ms-excel",
        success: function (data) {
            console.log(data);

        },
        error: function (errorMsg) {
            //请求失败时执行该函数
            alert("导出失败!");
        }
    })

从上面代码看,有四种方法可以从后台获取语言件流,供后续使用。这四种方未能分别都试过,原来以为前后端文件流格式不一样导致,由于开发环境没这个问题,只有生产环境有。开发环境与测试环境不一样真是问题大啊,整了一天都没有找到答案。
前端找不到答案只能继续在后台找,第二天折腾后台代码,网上打到一个旧的案例,死马当活马医,试试看,没想到用旧的代码虽然一堆过时的警告,上传到测试环境服务服务器竟然工作了,泪奔啊,代码如下,供大家参考:

  List<QuarantineExport> quarantineExports = employeeService.quarantineExportData(company, department, selectCodeColor, selectQuarState);
        String fileName = URLEncoder.encode("健康码统计信息.xls", "UTF-8");

        //写excel文件
        ExcelWriter writer = null;
        OutputStream outputStream = response.getOutputStream();
        try {
            //添加响应头信息
            response.setHeader("Content-disposition", "attachment; filename=" + fileName);
            response.setContentType("application/msexcel;charset=UTF-8");
            response.setHeader("Pragma", "No-cache");
            response.setHeader("Cache-Control", "no-cache");
            response.setDateHeader("Expires", 0);
            //实例化 ExcelWriter
            writer = new ExcelWriter(outputStream, ExcelTypeEnum.XLS, true);
            //实例化表单
            Sheet sheet = new Sheet(1, 0, QuarantineExport.class);
            sheet.setSheetName("隔离信息");
            //输出
            writer.write(quarantineExports, sheet);
            writer.finish();
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                response.getOutputStream().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

三、问题原因

搞了一天都没搞定,找到了EasyExcel钉钉群,刚好EasyExcel作之一庄家钜在群中解签问题,在此感谢作都的提示。
作都提示open jdk存在字体不全的问题,可能导致类似问题。
又找了一圈,没有解决问题的头绪,网上有一个说是将生产环境换为oracle JdK,哎,oracle JDK修订版不是免费的啊,这是一个写着玩的项目,算了,继续用过时的方法吧。
注意这个过时的方法导出的excel文件是低版本的,够用了,文件扩展名只能为xls,不要用xlsx否则打不开。
如正式要用,还是将open jdk字体安装全,或都用oracle jdk吧。这是恢复编程学习以来遇到最大的一个坑,坑了我2天时间,特记录。
老伍。

评论 7
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值