摘要:基于实现的文档转换项目,无框架依赖,即插即用项目源代码技术栈功能使用安装配置获取依赖编辑配置文件执行转换按照文件路径转换按照输入输出流转换按照文件转换图片处理按照文件路径处理按照文件处理添加水印按照文件路径添加水印按照流添加水印按照添加水
基于libreoffice实现的文档转换项目,无框架依赖,即插即用
项目源代码:github/workable-converter
1. 技术栈
2. 功能
3. 使用
3.1 安装配置LibreOffice6.2.3
3.2 获取依赖
3.3 编辑配置文件
3.4 执行转换
3.4.1 按照文件路径转换
3.4.2 按照输入输出流转换
3.4.3 按照文件Base64转换
3.5 图片处理
3.5.1 按照文件路径处理
3.5.2 按照文件Base64处理
3.6 添加水印
3.6.1 按照文件路径添加水印
3.6.2 按照流添加水印
3.6.3 按照base64添加水印
4. 待办事项
5. 注意事项
6. 参考链接
1. 技术栈LibreOffice:v6.2.3
jodconverter:4.2.2
PDFBox:2.0.12
cglib动态代理 + 懒汉工厂模式 + 策略模式 + 装饰器模式
qtools-property管理配置文件(application.yml、bootstrap.yml、workable-converter.yml三种命名的配置文件任意包含一种即可)
2. 功能支持doc、docx、html、ppt、png、pdf等等类型的文件互相转换
支持按照文件路径、字节输入输出流、Base64等不同姿势转换
不依赖第三方框架,即插即用,支持application.yml、bootstrap.yml、workable-converter.yml三种配置(自己项目中具体配置一个即可)
3. 使用 3.1 安装配置LibreOffice6.2.3CentOS请直接参考这篇文章:CentOS7安装LibreOffice6.2.3
windows跟Mac同样可以在上述文章中拿到下载链接
安装完成后,请记住您的LibreOffice的Home目录,后面需要用到
默认目录:
CentOS: /opt/libreoffice6.2/
Mac: /Applications/LibreOffice.app/Contents/
Windows: C:Program FilesLibreOffice
3.2 获取依赖Maven
com.liumapp.workable.converter workable-converter v1.2.0
Gradle
compile group: "com.liumapp.workable.converter", name: "workable-converter", version: "v1.2.0"3.3 编辑配置文件
在项目的resources目录下,创建一个yml配置文件,需要确保文件名称为application.yml、bootstrap.yml或workable-converter.yml三种命名任意一个即可
添加以下配置:
com: liumapp: workable-converter: libreofficePath: "/Applications/LibreOffice.app/Contents"
libreofficePath的值为LibreOffice:6.2.3的安装目录
完整的配置项列表如下
参数名 | 解释 | 默认值 |
---|---|---|
libreofficePath | LibreOffice安装目录 | (String) 无默认值,该项必填 |
libreofficePort | LibreOffice监听端口 | (int) 2002 |
tmpPath | 临时存储目录 | (String) "./data/" |
以doc转PDF为例
WorkableConverter converter = new WorkableConverter();//实例化的同时,初始化配置项,配置项的校验通过Decorator装饰 ConvertPattern pattern = ConvertPatternManager.getInstance(); pattern.fileToFile("./data/test.doc", "./data/pdf/result1.pdf"); //test.doc为待转换文件路径,result1.pdf为转换结果存储路径 pattern.setSrcFilePrefix(DefaultDocumentFormatRegistry.DOC); pattern.setDestFilePrefix(DefaultDocumentFormatRegistry.PDF); converter.setConverterType(CommonConverterManager.getInstance());//策略模式,后续实现了新的转换策略后,在此处更换,图片转换将考虑使用新的策略来完成 boolean result = converter.convert(pattern.getParameter();
如果要用html转PDF,将上述代码的
pattern.setSrcFilePrefix(DefaultDocumentFormatRegistry.DOC); pattern.setDestFilePrefix(DefaultDocumentFormatRegistry.PDF);
改为
pattern.setSrcFilePrefix(DefaultDocumentFormatRegistry.HTML); pattern.setDestFilePrefix(DefaultDocumentFormatRegistry.PDF);
其他类型的同理
3.4.2 按照输入输出流转换以doc转pdf为例
// you can also choice not use proxy WorkableConverter converter = new WorkableConverter(); ConvertPattern pattern = ConvertPatternManager.getInstance(); pattern.streamToStream(new FileInputStream("./data/test.doc"), new FileOutputStream("./data/pdf/result1_2.pdf")); // attention !!! convert by stream must set prefix. pattern.setSrcFilePrefix(DefaultDocumentFormatRegistry.DOC); pattern.setDestFilePrefix(DefaultDocumentFormatRegistry.PDF); converter.setConverterType(CommonConverterManager.getInstance()); boolean result = converter.convert(pattern.getParameter();
跟上例基本相同,唯一的变化是通过pattern.streamToStream()来设置输入输出流,转换源文件数据从输入流中读取,转换结果会直接写入输出流中,
同时要切换转换格式,跟上例一样设置不同的prefix即可
3.4.3 按照文件Base64转换仍以doc转pdf为例
WorkableConverter converter = new WorkableConverter(); ConvertPattern pattern = ConvertPatternManager.getInstance(); pattern.base64ToBase64(Base64FileTool.FileToBase64(new File("./data/test.doc"))); // attention !!! convert by base64 must set prefix. pattern.setSrcFilePrefix(DefaultDocumentFormatRegistry.DOC); pattern.setDestFilePrefix(DefaultDocumentFormatRegistry.PDF); converter.setConverterType(CommonConverterManager.getInstance()); boolean result = converter.convert(pattern.getParameter(); String destBase64 = pattern.getBase64Result();
输入base64执行转换,首先通过pattern.base64ToBase64()来设置转换源的base64值
转换结果result仍然是一个boolean类型,通过pattern.getBase64Result来获取转换结果的base64值
要切换转换格式,跟上例一样设置不同的prefix即可
3.5 图片处理目前对于图片的处理,只支持将PDF转PNG图片(如果1份pdf文件有20页,那么将会转换为20张png图片),该功能的实现基于PDFBox:2.0.12
3.5.1 按照文件路径处理pattern.fileToFiles()第一个参数为待转换的pdf文件路径,第二个参数为转换后的图片存储路径
WorkableConverter converter = new WorkableConverter(); ConvertPattern pattern = ConvertPatternManager.getInstance(); pattern.fileToFiles("./data/test5.pdf", "./data/"); pattern.setSrcFilePrefix(DefaultDocumentFormatRegistry.PDF); pattern.setDestFilePrefix(DefaultDocumentFormatRegistry.PNG); converter.setConverterType(PdfBoxConverterManager.getInstance()); // pdf box converter manager only support pdf to png assertEquals(true, converter.convert(pattern.getParameter())); assertEquals(true, FileTool.isFileExists("./data/test5_0.png")); assertEquals(true, FileTool.isFileExists("./data/test5_1.png")); assertEquals(true, FileTool.isFileExists("./data/test5_2.png")); assertEquals(true, FileTool.isFileExists("./data/test5_3.png"));3.5.2 按照文件Base64处理
pattern.base64ToBase64()的参数为待转换pdf文件的base64值
转换结束后,通过List
WorkableConverter converter = new WorkableConverter(); ConvertPattern pattern = ConvertPatternManager.getInstance(); pattern.base64ToBase64(Base64FileTool.FileToBase64(new File("./data/test5.pdf"))); pattern.setSrcFilePrefix(DefaultDocumentFormatRegistry.PDF); pattern.setDestFilePrefix(DefaultDocumentFormatRegistry.PNG); converter.setConverterType(PdfBoxConverterManager.getInstance()); // pdf box converter manager only support pdf to png boolean result = converter.convert(pattern.getParameter()); List3.6 添加水印resultBase64 = pattern.getBase64Results(); assertEquals(true, result); assertEquals(4, resultBase64.size());
水印的转换策略为WaterMarkConverter
添加水印注意事项
请确保输入源文件后缀为PDF,输出源文件后缀也为PDF
水印参数需要new一个WaterMarkRequire来设置
setWaterMarkPage(int page)代表在哪一页上添加水印,如果为0,则表示所有页面
水印本身为一个PDF文件,该文件只需要一页,其第一页的内容将被视为水印添加到源文件中
比如说,要添加透明度为0.3的文本作为水印的话,自己使用word等工具绘制透明度为0.3的字体(或者上包含透明度的png图片也可以)并另存为一个watermark.pdf文件
然后使用waterMarkRequire.setWaterMarkPDFBase64(Base64FileTool.FileToBase64(new File("./data/watermark.pdf")))
或者waterMarkRequire.setWaterMarkPDFBytes(FileUtils.readFileToByteArray(new File("./data/watermark.pdf")))将该文件的base64或者bytes值输入即可
具体使用可以分为三种方式
3.6.1 按照文件路径添加水印WorkableConverter converter = new WorkableConverter(); converter.setConverterType(WaterMarkConverterManager.getInstance());//选择具体的水印转换策略 ConvertPattern pattern = ConvertPatternManager.getInstance(); WaterMarkRequire waterMarkRequire = new WaterMarkRequire();//创建水印所需要的参数 //指定在具体的哪一页添加水印,0的话则在所有页面添加水印 waterMarkRequire.setWaterMarkPage(0);//0 means all age waterMarkRequire.setWaterMarkPDFBase64(Base64FileTool.FileToBase64(new File("./data/watermark.pdf"))); pattern.setWaterMarkRequire(waterMarkRequire); pattern.setSrcFilePrefix(DefaultDocumentFormatRegistry.PDF); pattern.setDestFilePrefix(DefaultDocumentFormatRegistry.PDF); pattern.fileToFile("./data/test5.pdf", "./data/test5_with_mark01.pdf");//添加水印后的文件保存在./data/目录下,名为test5_with_mark01.pdf boolean result = converter.convert(pattern.getParameter()); assertEquals(true, result);3.6.2 按照流添加水印
WorkableConverter converter = new WorkableConverter(); converter.setConverterType(WaterMarkConverterManager.getInstance()); ConvertPattern pattern = ConvertPatternManager.getInstance(); WaterMarkRequire waterMarkRequire = new WaterMarkRequire(); waterMarkRequire.setWaterMarkPage(0);//0 means all age waterMarkRequire.setWaterMarkPDFBytes(FileUtils.readFileToByteArray(new File("./data/watermark.pdf"))); pattern.setWaterMarkRequire(waterMarkRequire); pattern.setSrcFilePrefix(DefaultDocumentFormatRegistry.PDF); pattern.setDestFilePrefix(DefaultDocumentFormatRegistry.PDF); pattern.streamToStream(new FileInputStream("./data/test5.pdf"), new FileOutputStream("./data/test5_with_mark02.pdf")); boolean result = converter.convert(pattern.getParameter()); assertEquals(true, result);3.6.3 按照base64添加水印
WorkableConverter converter = new WorkableConverter(); converter.setConverterType(WaterMarkConverterManager.getInstance()); ConvertPattern pattern = ConvertPatternManager.getInstance(); WaterMarkRequire waterMarkRequire = new WaterMarkRequire(); waterMarkRequire.setWaterMarkPage(0);//0 means all age waterMarkRequire.setWaterMarkPDFBase64(Base64FileTool.FileToBase64(new File("./data/watermark.pdf"))); pattern.setWaterMarkRequire(waterMarkRequire); pattern.setSrcFilePrefix(DefaultDocumentFormatRegistry.PDF); pattern.setDestFilePrefix(DefaultDocumentFormatRegistry.PDF); pattern.base64ToBase64(Base64FileTool.FileToBase64(new File("./data/test5.pdf"))); boolean result = converter.convert(pattern.getParameter()); String base64Result = pattern.getBase64Result(); Base64FileTool.saveBase64File(base64Result, "./data/test5_with_mark03.pdf"); assertEquals(true, result);4. 待办事项
已经测试通过的有doc、docx、html 按照不同姿势转PDF,其他类型的并没有编写测试单元,后续考虑增加
目前只支持yml配置,后续考虑添加其他类型的配置支持(xml、properties等)
目前Markdown格式很流行,考虑实现markdown格式的字符串转PDF(markdown -> html -> pdf)
5. 注意事项因为需要LibreOffice的支持,所以不建议在Docker等容器内运行(LibreOffice暂无Docker稳定发行版的镜像)
转换乱码、转换耗时过长,请检查服务器是否安装有中文字体
项目启动后,在执行第一次转换任务时,因为涉及到与LibreOffice建立连接等操作,所以会耗时较长,第二次任务及以后稳定在0.5秒以内(具体时间因机器配置会有所差异)
6. 参考链接https://www.libreoffice.org/d...
https://api.libreoffice.org/
https://github.com/sbraconnie...
https://memorynotfound.com/ap...
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/75820.html
摘要:文档基金会已经宣布推出标签下的日志,这是办公套件的一个重要的新版本,带有大量的互操作性改进,以更好地支持微软格式,如和。新的更新还增加了对苹果芯片的原生支持,不过,出于稳定性考虑,建议用户使用旧的二进制类型。另外的来自于名个人志愿者。The Document Foundation(文档基金会)已经宣布推出 LibreOffice 7.2,这是办公套件的一个重要的新版本,带有大量的互操作性改进...
摘要:用将文档转换本例使用。在和环境下测试通过。转换命令源文件放在或者封装了一组转换命令,通过调用相关服务。安装检查已有字体库复制字体新建文件夹把系统的字体复制进去。 用LibreOffice将Office文档转换PDF 本例使用 LibreOffice-6.0.4、jodconverter-4.2.0、spring-boot-1.5.9.RELEASE。 在CentOS7 + ope...
摘要:在这里,老蒋推荐这款办公套装,完全是免费开源且跨平台的办公软件。因为老蒋是测试这款办公软件的,我就不选择单独的软件路径,直接默认。这样,正如有些网友说的,在一定程度上还是可以取代微软软件的。一般来说,我们购买的电脑是自带正版WIN系统的会同时自带正版Microsoft Office套件办公软件,这样我们就无需购买或者寻找免费的办公软件。但是,我们有些朋友的电脑系统并非正版的,或者我们在使用m...
摘要:项目需求在前端页面中实现预览表格的功能,上网了解之后大致总结为一下几种方法。第四种方法把表格打开后,另存为格式的文件。在网页上预览效果和表格一致。 项目需求在前端页面中实现预览excel表格的功能,上网了解之后大致总结为一下几种方法。 1.office文档转换为pdf,再转swf,然后通过网页加载flash进行预览 2.通过 xlsx.js,jszip.js插件 3.django xl...
阅读 1294·2021-11-24 10:24
阅读 3900·2021-11-22 15:29
阅读 1034·2019-08-30 15:53
阅读 2768·2019-08-30 10:54
阅读 1951·2019-08-29 17:26
阅读 1236·2019-08-29 17:08
阅读 581·2019-08-28 17:55
阅读 1553·2019-08-26 14:01