在做文件在线预览的时候,由于用 OpenOffice、LibreOffice 转换 Office 文档成 pdf 都会存在一定不可避免的失真,为了解决这个问题,又用了 Jacob 来对文档进行转换,测试后发现这个工具转换出来的文档效果和原文件基本相同,所以在这边做个记录,仅供大家参考。
一、安装 Office/WPS
因为文档转换需要用到 Office/WPS 软件,所以需要提前在机子上装好,这里我用的是 Office2016 全家桶。
二、下载 Jacob
下载 Jacob,建议去 Jacob 官网 下载,我下载的是最新的版本 1.19,压缩包内包含的文件如下:
三、配置 JDK
这里根据系统的版本,需要把 dll 文件放到 JDK 的 bin 目录下,我机子的路径如下:
注意:因为 Linux 不识别 dll 文件,所以这个应该只能在 Windows 系统上跑
四、导入 jar 包
这里我创建的是 SpringBoot 项目,因为 maven 中央仓库找不到 Jacob 的包,所以这里我先把 jacob.jar
导入本地 maven 仓库;
打开 CMD 先进入刚才下载的压缩包的解压缩目录,就是 jacob.jar 的文件目录下执行:
mvn install:install-file -Dfile=jacob.jar -DgroupId=com.jacob -DartifactId=jacob -Dversion=1.19 -Dpackaging=jar
成功后 pom 文件下引入依赖:
<dependency>
<groupId>com.jacob</groupId>
<artifactId>jacob</artifactId>
<version>1.19</version>
</dependency>
五、转换实现
这里我只用到了 word 类文档转 pdf、ppt 类文档转 pdf、excel 类文档转 html,下面贴上代码:
/**
* word文件转pdf
* @param source
* @param target
*/
public static void word2pdf(String source, String target) throws Exception {
ComThread.InitSTA();
ActiveXComponent app = null;
Dispatch doc = null;
try {
//创建一个Word对象
app = new ActiveXComponent("Word.Application");
app.setProperty("Visible", false);
Dispatch docs = app.getProperty("Documents").toDispatch();
/*
* 打开激活文档
* param 4: ReadOnly
* param 5: Untitled指定文件是否有标题
* param 6: WithWindow指定文件是否可见
* */
doc = Dispatch.call(docs, "Open", source, false, true).toDispatch();
File tofile = new File(target);
if (tofile.exists()) {
tofile.delete();
}
//word保存为pdf的宏值为17
Dispatch.call(doc, "SaveAs", target, 17);
} finally {
if(doc != null) {
Dispatch.call(doc, "Close", false);
}
if (app != null) {
app.invoke("Quit", new Variant[] {});
}
ComThread.Release();
}
}
/**
* ppt转pdf
* @param source
* @param target
* @throws Exception
*/
public static void ppt2pdf(String source, String target) throws Exception {
ComThread.InitSTA();
ActiveXComponent app = null;
Dispatch ppt = null;
try {
app = new ActiveXComponent("PowerPoint.Application");
app.setProperty("Visible", true);
Dispatch ppts = app.getProperty("Presentations").toDispatch();
ppt = Dispatch.call(ppts, "Open", source, false, false).toDispatch();
File tofile = new File(target);
if (tofile.exists()) {
tofile.delete();
}
//ppt转pdf的宏值为32
Dispatch.invoke(ppt, "SaveAs", Dispatch.Method, new Object[]{
target, 32},new int[1]);
} finally {
if(ppt != null) {
Dispatch.call(ppt, "Close");
}
if(app != null) {
app.invoke("Quit", new Variant[] {});
}
ComThread.Release();
}
}
/**
* excel转html
* @param source
* @param target
*/
public static void excel2html(String source, String target) throws Exception {
ComThread.InitSTA();
ActiveXComponent app = null;
Dispatch excel = null;
try {
app = new ActiveXComponent("Excel.Application");
app.setProperty("Visible", false);
Dispatch excels = app.getProperty("Workbooks").toDispatch();
excel = Dispatch.invoke(
excels,
"Open",
Dispatch.Method,
new Object[] { source, false,
true}, new int[1]).toDispatch();
File tofile = new File(target);
if (tofile.exists()) {
tofile.delete();
}
//excel转Html的宏值为44
Dispatch.invoke(excel, "SaveAs", Dispatch.Method, new Object[] {
target, 44}, new int[1]);
//Excel转换后需要转码成UTF-8,否则预览可能会乱码
html2utf(target);
html2utfForJacob(target);
} finally {
if(excel != null) {
Dispatch.call(excel, "Close", false);
}
if(app != null) {
app.invoke("Quit", new Variant[] {});
}
ComThread.Release();
}
}
public static void html2utf(String filePath) throws Exception {
String content = "charset=utf-8";
String templateContent = "";
FileInputStream fileinputstream = new FileInputStream(filePath);// 读取模板文件
//获得输入流的长度,然后建一个该长度的数组,然后把输入流中的数据以字节的形式读入到数组中,然后关闭流
int lenght = fileinputstream.available();
byte bytes[] = new byte[lenght];
fileinputstream.read(bytes);
fileinputstream.close();
//因为原来的html文件是gb2312格式,所以转为string时也要以GBK格式读取,不然依旧是乱码
templateContent = new String(bytes, "GBK");
templateContent = templateContent.replaceFirst("charset=gb2312", content);
// 因为已经替换字符串了,所以使用UTF-8字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
byte tag_bytes[] = templateContent.getBytes("UTF-8");
FileOutputStream fileoutputstream = new FileOutputStream(filePath);// 建立文件输出流
fileoutputstream.write(tag_bytes);
fileoutputstream.close();
}
public static void html2utfForJacob(String filePath) throws Exception {
filePath = filePath.replace(".html", ".files");
File dir = new File(filePath);
File[] files = dir.listFiles(); // 该文件目录下文件全部放入数组
if (files != null) {
for (int i = 0; i < files.length; i++) {
String fileName = files[i].getName();
if (files[i].isDirectory()) { // 判断是文件还是文件夹
html2utfForJacob(files[i].getAbsolutePath()); // 获取文件绝对路径
} else if (fileName.endsWith("html")) { // 判断文件名是否以.html结尾
String strFileName = files[i].getAbsolutePath();
html2utf(strFileName) ;
} else {
continue;
}
}
}
}
public static void main(String[] args) {
Long a = System.currentTimeMillis();
try {
word2pdf("E:\\conventor\\1.docx", "E:\\conventor\\1.pdf");
//ppt2pdf("E:\\conventor\\2.ppt", "E:\\conventor\\2.pdf");
//excel2html("E:\\conventor\\3.xlsx", "E:\\conventor\\3.html");
} catch(Exception e) {
e.printStackTrace();
}
Long b = System.currentTimeMillis();
Long q = (b-a)/1000;
System.out.println("===转换成功===, 耗时" + q + "s");
}
问题:在 main 函数中能够运行 ppt2pdf 函数转换文档,但是在项目中调用这个函数就会报错:
稍微调大了 JDK 内存也仍然报错,不知道什么原因,希望有懂的大神可以不吝赐教 ^^
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于