废话不多说直接进入正题,首先分析生成pdf场景及生成内容,考虑复用性和维护难度是我们当前开发工作的第一要务!
下面是调研的几个主要方案:
一、itext 表单填充
使用方式:
itext表单填充方案是以pdf作为基础模板,通过在pdf中嵌入表单元素组件的方式(需要使用pdf编辑工具),最后由程序进行数据填充并另存为pdf结果。
方案优缺点:
优点:代码优雅,生成后格式变化影响极小。
缺点:原始模板变化需要重新生成pdf,重新编辑表单元素;不支持列表填充数据。
基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
项目地址:https://gitee.com/zhijiantianya/ruoyi-vue-pro
视频教程:https://doc.iocoder.cn/video/
二、freemarker + doc4J 基于Word 生成 PDF
使用方式:
首先将调整好格式的原始 word 导出为 XML 格式,编辑 XML 模板中需要填充元素的位置,最后由程序处理先由freemarker模板工具替换元素内容,再使用doc4J进行pdf导出。
方案优缺点:
优点:通用性强,基于模板引擎功能强大。
缺点:XML 格式的word真的有够复杂,想要在此模板上调整样式真的难上加难;由于系统不支持的原因需要导入中文字体库;doc4J 部分 doc 元素不支持(例如直线),导出格式差异较大。
这可能是由于doc4J迭代问题无法保证新元素的支持,导出结果比较奔放。。。
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
三、freemarker + aspose-words 导出PDF
使用方式:
类似于 freemarker+doc4J 方式,同样需要编辑XML,导出格式相较doc4J而言有极大提升。
方案优缺点:
优点:通用性强,基于模板引擎功能强大,无需手工管理字体(macOS),代码简单,导出格式与模板基本无差异。
缺点:需要编辑 XML 模板;该方案不是免费版(当然有大神)。
受限于调试前期需要的修修改改,模板能给人整吐了,所以才有了下一个方案。
四、html + freemarker + itextpdf(html2pdf)
使用方式:
翻译 word 为 html 页面(当然就是手写啦,还原度很重要!),html中模板元素插入(文字填充、列表循环 freemarker 支持的全都能写),最后由程序处理先由freemarker模板工具替换元素内容,再使用html2pdf进行pdf导出。
方案优缺点:
优点:可维护性相较与上面方案都有极大提升(调试可见性,动态替换生效);通用性强,基于模板引擎功能强大;导出格式可控性较强;
缺点:需要中文字体库。
这个方案是综合以上多次踩坑的结果,结果是显而易见的。
浅浅来一点代码,省的大家到处找
com.itextpdf itextpdf 5.5.13 com.itextpdf html2pdf 3.0.3 org.xhtmlrenderer flying-saucer-pdf-itext5 9.0.3 binarta.oss groovy-template-enginex-freemarker 0.1.3
个人以为自己的代码会自解释,就不贴太多注释了
importcn.hutool.core.io.FileUtil; importcn.hutool.core.map.MapUtil; importcom.google.common.collect.Lists; importcom.itextpdf.text.pdf.BaseFont; importfreemarker.cache.ByteArrayTemplateLoader; importfreemarker.template.Configuration; importfreemarker.template.Template; importlombok.SneakyThrows; importorg.xhtmlrenderer.pdf.ITextFontResolver; importorg.xhtmlrenderer.pdf.ITextRenderer; importjava.io.BufferedWriter; importjava.io.ByteArrayOutputStream; importjava.io.File; importjava.io.StringWriter; importjava.nio.charset.Charset; importjava.nio.charset.StandardCharsets; importjava.util.List; importjava.util.Locale; importjava.util.Map; importjava.util.Objects; importjava.util.function.Supplier; publicclassHtmlToPdfUtil{ privatestaticfinalByteArrayTemplateLoaderTEMPLATE_LOADER=newByteArrayTemplateLoader(); //导入需要字体库的位置哦;simsun 为宋体 publicstaticfinalStringFRONT_PATH="/usr/share/fonts/simsun.ttc"; /** *看明白的话只用这个方法就够 */ publicstaticByteArrayOutputStreamhtmlToPdf(StringtemplateName,SupplierloadTemplateSupplier,Map modeViewMap){ Stringhtml=xmlFormat(templateName,loadTemplateSupplier,modeViewMap); returnhtmlToPdf(html); } @SneakyThrows publicstaticByteArrayOutputStreamhtmlToPdf(StringhtmlStr){ ByteArrayOutputStreamoutputStream=newByteArrayOutputStream(); ITextRendererrenderer=newITextRenderer(); renderer.setDocumentFromString(htmlStr); ITextFontResolverresolver=renderer.getFontResolver(); //添加字体,解决中文不显示的问题 resolver.addFont(FRONT_PATH,BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED); renderer.layout(); renderer.createPDF(outputStream); returnoutputStream; } publicstaticStringxmlFormat(StringtemplateName,Supplier loadTemplateSupplier,Map modeViewMap){ if(Objects.isNull(TEMPLATE_LOADER.findTemplateSource(templateName))){ synchronized(TEMPLATE_LOADER){ if(Objects.isNull(TEMPLATE_LOADER.findTemplateSource(templateName))){ TEMPLATE_LOADER.putTemplate(templateName,loadTemplateSupplier.get()); } } } returnxmlFormat(templateName,modeViewMap); } @SneakyThrows publicstaticStringxmlFormat(StringtemplateName,Map modeViewMap){ Configurationcfg=newConfiguration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS); //指定FreeMarker模板文件的位置 cfg.setTemplateLoader(TEMPLATE_LOADER); //设置模板的编码格式 cfg.setEncoding(Locale.CHINA,Charset.defaultCharset().name()); //获取模板文件template Templatetemplate=cfg.getTemplate(templateName,Charset.defaultCharset().name()); StringWriterstringWriter=newStringWriter(); BufferedWriterwriter=newBufferedWriter(stringWriter); template.process(modeViewMap,writer); returnstringWriter.toString(); } }
结
解决这个问题的核心思路方案其实一直没变,变化的只是工具,一定要思路清晰!
审核编辑:刘清
-
XML
+关注
关注
0文章
188浏览量
33068 -
HTML
+关注
关注
0文章
278浏览量
35074
原文标题:服务端自定义生成PDF的几种方案
文章出处:【微信号:芋道源码,微信公众号:芋道源码】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论