【Docker】poi和easyExcel本地正常导出,但是线上部署到docker后导出报错解决方法

前言

  • 开发了一个用poi工具导出excel表的接口,本地测试正常,但是部署到线上的测试环境后就一直报接口异常
  • 只要涉及在docker中导出excel文件的功能,基本都会有这个问题
  • 最后发现是docker基础镜像源openjdk缺少字体管理的问题,记录一下


解决方法和原因:

  • 方法1:直接替换DockerFile中的基础镜像源:FROM frolvlad/alpine-java:jdk8-slim(该镜像由网络用户提供,不保证安全性)

  • 方法2:在Dockerfile文件中追加构建命令 RUN apk add --update ttf-dejavu && rm -rf /var/cache/apk/*尝试下载字体(推荐,如果不行再尝试第一种方法)

  • 原因:导出excel时会根据字体大小调整列宽,本地开发时使用的时oracl的jdk8,所以没问题,但是部署到线上后打包的docker使用的open-jdk8-slim镜像源,此版本早已去除了libfontmanager字体的支持,需要我们自行下载,所以会导致导出时找不到字体管理器报错!坑爹

openjdk官方issue:Missing jdk8 packages after #322 #333

alibaba/easyexcel官方issue:download Excel 本地IntelliJ 调试正常,部署到docker异常#1077

alibaba/easyexcel官方issue:com.alibaba.excel.exception.ExcelGenerateException: java.lang.UnsatisfiedLinkError: /usr/lib/jvm/java-11-oracle/lib/libfontmanager.so: libfreetype.so.6: cannot open shared object file: No such file or directory #1533

一、 报错日志

  • 接口:poi插件导出excel的API

  • 环境:

    • 线下:oracle-jdk8 【导出接口正常】
    • 线上:docker基础镜像 open-jdk8-slim【导出接口异常】
  • 报错栈:

    stackTrace: org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.UnsatisfiedLinkError:/usr/local/openjdk-8/lib/amd64/libfontmanager.so: libfreetype.so.6: cannot open shared object file: No such file or directory\n\tat

二、 寻找原因

1. 在网络上搜索上边报错的栈信息,得到以下的可能原因

① Apache POI缺少动态库libfreetype.so

② Tomcat没有开启图像处理awt

③ Linux服务器缺少POI需要的字体(报错栈最直观的体现)

三、 解决思路

1、 尝试服务器下载对应的字体(无法解决)

  • apt -y install libfreetype6-dev

2、 尝试修改dockerFile文件命令重新构建附带字体的镜像(无法解决)

  • RUN apt install fontconfig -y --force-yes && apt install --fix-broken -y --force-yes

3、 尝试使用系统命令修改tomcat使用awt(没效果,无法解决)

4、 尝试修改镜像源(牛逼,轻松解决)

三、 错误原因总结

  • 线下开发时,使用的是oracl-jdk:8版本,在使用poi工具导出excel时,不会存在找不到字体的问题
  • 然而在使用docker部署到线上时使用的是openjdk:8-jre-slim,这个镜像没有libfontmanager链接库,会导致poi工具导出excel时调用字体库失败并报错,具体原因可以去最开头写的原因中查看官方的issue了解详情
  • 最终解决问题所用到的基础镜像源来自这篇文章:解决docker alpine缺少字体的问题
posted @ 2021-05-31 11:36  中国制造  阅读(8459)  评论(1编辑  收藏  举报