SpringBoot使用LibreOffice word转换PDF
由于java转pdf Aspose需要收费,documents4j是使用本地的MS Office应用做的文件格式转换,Linux没有对应的MS Office应用。这样造成了我们需要选用别的方式进行word的转换。思路:先用freemarker模板工具,生成docx文档,借助libreOffice将docx转pdf。1、 生成docx模板和xml模板......
由于java转pdf Aspose需要收费,documents4j是使用本地的MS Office应用做的文件格式转换,Linux没有对应的MS Office应用。这样造成了我们需要选用别的方式进行word的转换。思路:先用freemarker模板工具,生成docx文档,借助libreOffice将docx转pdf。
1、 生成docx模板和xml模板
docx模板:
xml模板:
用zip方式打开docx文档,拷贝word文件下的document.xml充当数据填充模板
2、freemarker填充数据
引入依赖
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.30</version>
</dependency>
利用document.xml模板写入数据并生成新的含有效数据的xml文件
public void createWord(ContractVO contractVO) throws Exception {
Configuration cfg = new Configuration(Configuration.VERSION_2_3_30);
cfg.setDefaultEncoding("UTF-8");
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
cfg.setLogTemplateExceptions(false);
cfg.setWrapUncheckedExceptions(true);
cfg.setDirectoryForTemplateLoading(new File(filePath));
Template t = cfg.getTemplate("document.xml");
// 导出文件
FileUtils.createFileDir(filePath + CONTRACT);
String fileName = contractVO.getCode() + "_" + contractVO.getBabyName() + "_" + "合同";
File outFile = new File(filePath + CONTRACT + fileName + ".xml");
try (Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), StandardCharsets.UTF_8))) {
// 将填充数据填入模板文件并输出到目标文件
t.process(convertToMap(contractVO), out);
} catch (Exception e) {
throw new CommonException("导出合同失败", e);
}
}
利用java的zipFile 和 ZipOutputStream 及zipFile.getInputStream() 来根据docx模板导出 (需要把word/document.xml文件替换成(填充完数据[document.xml文件回填])的xml)完成docx文档生成。
package com.icss.sywn.file.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
/**
* 其实docx属于zip的一种,这里只需要操作word/document.xml中的数据,其他的数据不用动
*
* @author wenbsu
*/
public class XmlToDocx {
/**
* @param documentFile 动态生成数据的docunment.xml文件
* @param docxTemplate docx的模板
* @param toFilePath 输出文档路径
*/
public static void outDocx(File documentFile, String docxTemplate, String toFilePath) {
try {
File docxFile = new File(docxTemplate);
ZipFile zipFile = new ZipFile(docxFile);
Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries();
ZipOutputStream zipout = new ZipOutputStream(new FileOutputStream(toFilePath));
int len = -1;
byte[] buffer = new byte[1024];
while (zipEntrys.hasMoreElements()) {
ZipEntry next = zipEntrys.nextElement();
InputStream is = zipFile.getInputStream(next);
// 把输入流的文件传到输出流中 如果是word/document.xml由我们输入
zipout.putNextEntry(new ZipEntry(next.toString()));
if ("word/document.xml".equals(next.toString())) {
InputStream in = new FileInputStream(documentFile);
while ((len = in.read(buffer)) != -1) {
zipout.write(buffer, 0, len);
}
in.close();
} else {
while ((len = is.read(buffer)) != -1) {
zipout.write(buffer, 0, len);
}
is.close();
}
}
zipout.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
3、docx 转 PDF
安装LibreOffice,下载地址:https://www.libreoffice.org/download/download/
引入依赖
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-core</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-local</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-spring-boot-starter</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>org.libreoffice</groupId>
<artifactId>ridl</artifactId>
<version>5.4.2</version>
</dependency>
配置application.yml
jodconverter:
local:
enabled: true
office-home: C:\\Program Files\\LibreOffice
port-numbers: 2002
转换pdf
package com.icss.sywn.file.util;
import lombok.extern.slf4j.Slf4j;
import org.jodconverter.DocumentConverter;
import org.jodconverter.document.DefaultDocumentFormatRegistry;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.io.File;
@Slf4j
@Component
public class DocumentConverterUtil {
@Resource
private DocumentConverter documentConverter;
public String convert(File in, File out) {
try {
long startTime = System.currentTimeMillis();
documentConverter.convert(in).as(DefaultDocumentFormatRegistry.HTML)
.to(out).as(DefaultDocumentFormatRegistry.PDF).execute();
long conversionTime = System.currentTimeMillis() - startTime;
log.info(String.format("successful conversion: %s to %s in %dms", in.getName(), "pdf", conversionTime));
} catch (Exception e) {
e.printStackTrace();
return "FAIL";
}
return "SUCCESS";
}
}
完成window环境下生成docx 转 pdf操作,如果是linux环境需要在linux系统安装LibreOffice
操作如下:
1、下载rpm包并解压https://mirrors.cloud.tencent.com/libreoffice/libreoffice/stable/
2、安装
yum install /root/LibreOffice_7.3.1.3_Linux_x86-64_rpm/RPMS/*.rpm
yum install /root/LibreOffice_7.3.1.3_Linux_x86-64_rpm_langpack_zh-CN/RPMS/*.rpm
3、安装libcairo.so.2依赖库
yum install ibus
4、启动服务
安装路径:/opt/libreoffice7.3
快捷方式:/usr/bin/libreoffice7.3
/usr/bin/libreoffice7.3 --headless --accept="socket,host=127.0.0.1,port=8100;urp;" --nofirststartwizard
5、安装字体
在CentOS7服务器上,利用LibreOffice将word等格式转换为PDF,发现不支持汉字。需要安装字体库。
yum -y install fontconfig
安装完成后,/usr/share目录就可以看到fonts和fontconfig两个目录。
yum -y install ttmkfdir
检查已有字体库
fc-list
复制字体
mkdir /usr/share/fonts/chinese
把docx中用到的字体copy到chinese文件夹里边
修改权限
chmod -R 644 /usr/share/fonts/chinese
汇总生成fonts.scale文件
ttmkfdir /usr/share/fonts/chinese
修改字体配置文件
vim /etc/fonts/fonts.conf
修改的内容如下
<fontconfig>
....
<dir>....
<dir>/usr/share/fonts/chinese</dir>
....
</fontconfig>
更新字体缓存
fc-cache -fv
如果转码出现乱码方格情况,需要把window下docx用到的字体都拷到/opt/libreoffice7.3/share/fonts/truetype目录下,重启服务就可以。
更多推荐
所有评论(0)