easyexecl导出100万行execl报字体错误的解决办法

x33g5p2x  于2022-06-29 转载在 其他  
字(6.2k)|赞(0)|评价(0)|浏览(689)

使用easyexecl做100万行csv的导出,会报两个错误,都是因为openjdk精简版安装到docker内部,缺少字体的问题。

错误明细:

/usr/local/openjdk-17/lib/libfontmanager.so: libfreetype.so.6: cannot open shared object file: No such file or directory
2022-06-24 14:39:00.045  INFO 1 --- [nio-5010-exec-2] c.f.b.b.c.BillingDetailController        : 导出execl1656081540043
2022-06-24 14:39:05.980 ERROR 1 --- [nio-5010-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is com.alibaba.excel.exception.ExcelGenerateException: java.lang.UnsatisfiedLinkError: /usr/local/openjdk-17/lib/libfontmanager.so: libfreetype.so.6: cannot open shared object file: No such file or directory] with root cause

java.lang.UnsatisfiedLinkError: /usr/local/openjdk-17/lib/libfontmanager.so: libfreetype.so.6: cannot open shared object file: No such file or directory
 at java.base/jdk.internal.loader.NativeLibraries.load(Native Method) ~[na:na]
 at java.base/jdk.internal.loader.NativeLibraries$NativeLibraryImpl.open(NativeLibraries.java:388) ~[na:na]
 at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:232) ~[na:na]
 at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:174) ~[na:na]
 at java.base/jdk.internal.loader.NativeLibraries.findFromPaths(NativeLibraries.java:315) ~[na:na]
 at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:285) ~[na:na]
 at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2398) ~[na:na]
 at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:818) ~[na:na]
 at java.base/java.lang.System.loadLibrary(System.java:1989) ~[na:na]
 at java.desktop/sun.font.FontManagerNativeLibrary$1.run(FontManagerNativeLibrary.java:58) ~[na:na]
 at java.base/java.security.AccessController.doPrivileged(AccessController.java:318) ~[na:na]
 at java.desktop/sun.font.FontManagerNativeLibrary.<clinit>(FontManagerNativeLibrary.java:33) ~[na:na]
 at java.desktop/sun.font.SunFontManager$1.run(SunFontManager.java:275) ~[na:na]
 at java.desktop/sun.font.SunFontManager$1.run(SunFontManager.java:273) ~[na:na]
 at java.base/java.security.AccessControlle

或者

java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11FontManager
nerateException: java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11FontManager] with root cause

java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11FontManager
 at java.base/java.lang.Class.forName0(Native Method) ~[na:na]
 at java.base/java.lang.Class.forName(Class.java:467) ~[na:na]
 at java.desktop/sun.font.FontManagerFactory$1.run(FontManagerFactory.java:83) ~[na:na]
 at java.base/java.security.AccessController.doPrivileged(AccessController.java:318) ~[na:na]
 at java.desktop/sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:75) ~[na:na]
 at java.desktop/java.awt.Font.getFont2D(Font.java:526) ~[na:na]
 at java.desktop/java.awt.Font.canDisplayUpTo(Font.java:2282) ~[na:na]
 at java.desktop/java.awt.font.TextLayout.singleFont(TextLayout.java:469) ~[na:na]
 at java.desktop/java.awt.font.TextLayout.<init>(TextLayout.java:530) ~[na:na]
 at org.apache.poi.ss.util.SheetUtil.getDefaultCharWidth(SheetUtil.java:273) ~[poi-4.1.2.jar:4.1.2]
 at org.apache.poi.xssf.streaming.AutoSizeColumnTracker.<init>(AutoSizeColumnTracker.java:117) ~[poi-ooxml-4.1.2.jar:4.1.2]
 at org.apache.poi.xssf.streaming.SXSSFSheet.<init>(SXSSFSheet.java:82) ~[poi-ooxml-4.1.2.jar:4.1.2]
 at org.apache.poi.xssf.streaming.SXSSFWorkbook.createAndRegisterSXSSFSheet(SXSSFWorkbook.java:684) ~[poi-ooxml-4.1.2.jar:4.1.2]
 at org.apache.poi.xssf.streaming.SXSSFWorkbook.createSheet(SXSSFWorkbook.java:705) ~[poi-ooxml-4.1.2.jar:4.1.2]
 at org.apache.poi.xssf.streaming.SXSSFWorkbook.createSheet(SXSSFWorkbook.java:88) ~[poi-ooxml-4.1.2.jar:4.1.2]
 at com.alibaba.excel.util.WorkBookUtil.createSheet(WorkBookUtil.java:84) ~[easyexcel-core-3.1.1.jar:na]
 at com.alibaba.excel.context.WriteContextImpl.createSheet(WriteContextImpl.java:223) ~[easyexcel-core-3.1.1.jar:na]
 at com.alibaba.excel.context.WriteContextImpl.initSheet(WriteContextImpl.java:182) ~[easyexcel-core-3.1.1.jar:na]
 at com.alibaba.excel.context.WriteContextImpl.currentSheet(WriteContextImpl.java:135) ~[easyexcel-core-3.1.1.ja

需要重新做一个镜像,以openjdk17为例

1、编辑dockerfile文件

FROM openjdk:17-alpine

# 解决easyExcel导出缺少字体bug
RUN apk add --update ttf-dejavu fontconfig && rm -rf /var/cache/apk/*

2、IDEA配置docker插件

安装步骤可以自己google一下

3、安装Docker Desktop

安装配置及其注册,可以google查询

4、运行dockerfile

5、推送并查看docker-hub上是否有了,注意一定要以自己的用户名字打tag,要不然会推送失败

6 、登录到需要的此镜像的服务器,将镜像拉下来或者配置gradle自动拉取镜像

或者配置依赖的镜像

7、重新部署应用,重新启动,即不报错

附注:esayExcel的导出代码

/**
	 * 导出excel
	 */
	@RequestMapping("/xxxexportcsv100")
	fun export(response: HttpServletResponse) {
		val startTime = System.currentTimeMillis()
		logger.info("导出execl$startTime")
		val outputStream: OutputStream = response.outputStream
		val time = SimpleDateFormat("yyyy-MM-dd-hh-mm-ss").format(Date())
		response.setHeader("Content-disposition", "attachment; filename=contract$time.xlsx")
		response.contentType = "application/octet-stream;charset=UTF-8"
		response.setHeader("Pragma", "No-cache")
		response.setHeader("Cache-Control", "no-cache")
		response.setDateHeader("Expires", 0)
		val count: Int = billingDetailService.countByIdIsNotNull()
		//如果总数据量多余10万,分页导出
		if (count > 100000) {
			//每页多少个
			val max = 100000
			//必须放到循环外,否则会刷新流
			val excelWriter: ExcelWriter = EasyExcel.write(outputStream).build()
			for (i in 0 until count / max + 1) {

				val exportList: List<BillingDetailResourceDto> = billingDetailService.findAllBySize(i, max)

				val writeSheet: WriteSheet =
					EasyExcel.writerSheet(i, "账单" + (i + 1)).head(BillingDetailResourceDto::class.java)
						.registerWriteHandler(LongestMatchColumnWidthStyleStrategy()).build()
				excelWriter.write(exportList, writeSheet)
				logger.info("100000行===${System.currentTimeMillis()}")
			}
			//刷新流
			excelWriter.finish()
		} else {
			val exportList: List<BillingDetailResourceDto> = billingDetailService.findAllBySize(0, count)
			EasyExcel.write(outputStream, BillingDetailResourceDto::class.java)
				.registerWriteHandler(LongestMatchColumnWidthStyleStrategy()).sheet("账单").doWrite(exportList)
		}
		outputStream.flush()
		response.outputStream.close()
		val endTime = System.currentTimeMillis()
		logger.info("导出execl结束$endTime==耗时=${endTime - startTime}")

	}

相关文章