资讯专栏INFORMATION COLUMN

工具库-基于LibreOffice实现文档操作

ZoomQuiet / 1250人阅读

摘要:基于实现的文档转换项目,无框架依赖,即插即用项目源代码技术栈功能使用安装配置获取依赖编辑配置文件执行转换按照文件路径转换按照输入输出流转换按照文件转换图片处理按照文件路径处理按照文件处理添加水印按照文件路径添加水印按照流添加水印按照添加水

基于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.3

CentOS请直接参考这篇文章: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/"
3.4 执行转换 3.4.1 按照文件路径转换

以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 resultBase64 = pattern.getBase64Results()获取转换后的图片base64值的集合

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());
List resultBase64 = pattern.getBase64Results();
assertEquals(true, result);
assertEquals(4, resultBase64.size());
3.6 添加水印

水印的转换策略为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

相关文章

  • LibreOffice 7.2 正式发布:原生适配苹果 M1 芯片,更好兼容微软 Office 文档

    摘要:文档基金会已经宣布推出标签下的日志,这是办公套件的一个重要的新版本,带有大量的互操作性改进,以更好地支持微软格式,如和。新的更新还增加了对苹果芯片的原生支持,不过,出于稳定性考虑,建议用户使用旧的二进制类型。另外的来自于名个人志愿者。The Document Foundation(文档基金会)已经宣布推出 LibreOffice 7.2,这是办公套件的一个重要的新版本,带有大量的互操作性改进...

    loonggg 评论0 收藏0
  • SpringBoot使用LibreOffice转换PDF

    摘要:用将文档转换本例使用。在和环境下测试通过。转换命令源文件放在或者封装了一组转换命令,通过调用相关服务。安装检查已有字体库复制字体新建文件夹把系统的字体复制进去。 用LibreOffice将Office文档转换PDF 本例使用 LibreOffice-6.0.4、jodconverter-4.2.0、spring-boot-1.5.9.RELEASE。 在CentOS7 + ope...

    mcterry 评论0 收藏0
  • LibreOffice – 免费跨平台办公套件可替代Microsoft Office套件

    摘要:在这里,老蒋推荐这款办公套装,完全是免费开源且跨平台的办公软件。因为老蒋是测试这款办公软件的,我就不选择单独的软件路径,直接默认。这样,正如有些网友说的,在一定程度上还是可以取代微软软件的。一般来说,我们购买的电脑是自带正版WIN系统的会同时自带正版Microsoft Office套件办公软件,这样我们就无需购买或者寻找免费的办公软件。但是,我们有些朋友的电脑系统并非正版的,或者我们在使用m...

    The question 评论0 收藏0
  • 在网页中预览excel表格文件

    摘要:项目需求在前端页面中实现预览表格的功能,上网了解之后大致总结为一下几种方法。第四种方法把表格打开后,另存为格式的文件。在网页上预览效果和表格一致。 项目需求在前端页面中实现预览excel表格的功能,上网了解之后大致总结为一下几种方法。 1.office文档转换为pdf,再转swf,然后通过网页加载flash进行预览 2.通过 xlsx.js,jszip.js插件 3.django xl...

    Honwhy 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<