个人理解和经验,有误的地方,还请指正
1.下载Jacob包。
2.将Jacob包中的Dll放在系统Jdk安装路径的jre->bin。
【如果是Tomcat需要将dll放在Tomcat的bin目录下】
3.正常来说到这一步是可以的(非Tomcat服务启动),
测试代码块:
/**
* docx文档转换为PDF
*
* @param temDir PDF文件路径
* @param wordPath Word路径
* @param fileName PDF文件名
* @throws Exception 可能为Docx4JException, FileNotFoundException, IOException等
*/
public static String convertDocxToPDF(String temDir, String wordPath) throws Exception {
//temDir PDF文件地址; wordPath Word文件地址 ;fileName PDF文件名
ActiveXComponent app = null;
String pdfFile = "";
InputStream in = null;
OutputStream out = null;
// 开始时间
long start = System.currentTimeMillis();
try {
log.info("1");
ComThread.InitSTA();
log.info("2");
// 打开word
app = new ActiveXComponent("Word.Application");//office
// app = new ActiveXComponent("kwps.Application");//wps(未测试过)
log.info("3");
// 设置word不可见默认就是不可见的
//app.setProperty("Visible", false);
// 获得word中所有打开的文档
Dispatch documents = app.getProperty("Documents").toDispatch();
System.out.println("打开文件: " + wordPath);
// 打开文档
Dispatch document = Dispatch.call(documents, "Open", wordPath, false, true).toDispatch();
// 如果文件存在的话,不会覆盖,会直接报错,所以我们需要判断文件是否存在
pdfFile = temDir;
File target = new File(pdfFile);
if (target.exists()) {
target.delete();
}
log.info("4");
// 另存为,将文档报错为pdf,其中word保存为pdf的格式宏的值是17
Dispatch.call(document, "SaveAs", pdfFile, 17);
// 关闭文档
Dispatch.call(document, "Close", false);
// 结束时间
long end = System.currentTimeMillis();
System.out.println("转换成功,用时:" + (end - start) + "ms");
log.info("5");
return pdfFile;
} catch (Exception e) {
e.getLocalizedMessage();
e.printStackTrace();
e.getMessage();
e.getCause();
e.getStackTrace();
e.getSuppressed();
System.out.println("转换失败" + e.getMessage());
System.out.println("转换失败" + e.getLocalizedMessage());
System.out.println("转换失败" + e.getSuppressed());
System.out.println("转换失败" + e.getStackTrace());
} finally {
// 关闭office
app.invoke("Quit", 0);
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
ComThread.Release();
// delTempFile(pdfFile);//
// delTempFile(wordPath);//
}
return pdfFile;
}
4.如果是Server 2008(我用的是Server 2016)之后的版本并且用Tomcat 通过服务启动程序,则需要以下操作:
(1)因为Server 2008之后好像是取消了COM对象默认的交互方式为“非交互”型,如果是通过 console启动程序不会有问题,但是如果是通过服务的形式启动就会有获取不到dll的问题。报错表现为 “Can't get object clsid from progid”
操作:下载Office(我是用的是2015,但是好像2003之后的到365都可以)或WPS(好像不能是简洁版)软件,操作目的是在系统注册表中生成对应软件的注册表(Office:Microsoft Word 97 - 2003 文档;WPS:WPS文字 文档),将注册表的属性->标识 改为交互式用户。
红字部分后续测试发现不是必须的。
【此处的软件和代码中 ActiveXComponent 要保持一致】
(2) 同样因为上述原因除了设置交互式用户外,在打开文件时因为文件操作需要一个Desktop文件夹所以需要在指定目录新建文件夹。报错表现为 “VariantChangeType failed”
操作:在 C:\Windows\System32\config\systemprofile 和C:\Windows\SysWOW64\config\systemprofile 目录下分别建 Desktop文件夹。
更新:如果上述步骤还是不行,可以进行以下操作
(1)进入 comexp.msc 编辑 Microsoft Word 97-2003 Document(WPS的是 Microsoft Word 06 - 07 Document ) 属性将安全中的访问权限设置为允许,将标识中的账户设置为启动用户;
注:Tomcat 服务中的账户类型要和该类型一致,即启动用户->本地系统账户;下列用户->此账户;
到这一步我碰到的问题就已经解决了,如果后续有新的问题会更新