调研后发现网上有很多解决办法,Windows平台上word和PDF可以完美的转换,但大部分业务是要求在Linux上运行的,基于Windows的方法无法移植到Linux上运行,现有的Linux上的Word文档转换为PDF的方法验证后大多数存在PDF和Word格式不一致的问题(比如PDF与Word排版页数不一致,文字排列更紧凑等),所以本文的主要目标是解决Linux平台上Word转为PDF之后的格式版面不一致的问题,先放结论,对于大部分测试用例文档格式在转换后基本一致,存在少部分不一致的问题。并且将java项目打包成jar包并在linux平台上调用命令行测试通过。
import win32com # python -m pip install pypiwin32
from win32com.client import Dispatch
import sys
def word2pdf(file_path='/documents/4-科园商务会议服务协议_20191105广州.doc'):
word = Dispatch('Word.Application')
word.Visible = 0 # 后台运行,不显示
word.DisplayAlerts = 0 #不警告
path = sys.path[0] + file_path
doc = word.Documents.Open(FileName=path, Encoding='gbk')
doc.SaveAs(path[:-5]+'_pdfed.pdf', 17) # txt=4, html=10, docx=16, pdf=17
doc.Close()
word.Quit()
print("Word2Pdf 转换完成,PDF文件和Word在同级目录中。")
if __name__ == '__main__':
# word2pdf('/documents/1-技术服务合同.docx')
file_path = sys.argv[1]
print(file_path)
word2pdf(file_path)
win32com只能在windows平台上运行,linux上没有类似的依赖包。
1.基于unoconv工具实现word转为PDF
安装:yum install unoconv
使用:unoconv -f pdf XXX.docx
2.使用cups-pdf工具实现word转PDF
安装:sudo apt-get install cups-pdf
使用:oowriter -convert-to pdf:writer_pdf_Export XXX.docx
3.使用libreoffice测试:
soffice --headless --invisible --convert-to pdf XXX.docx
4.使用apose-words-15.8.0工具hacked(pojie)版,java编程实现word转PDF。(推荐,目前验证该方法Word转为PDF后格式变化最小)
Eclipse项目目录结构:(文末有完整项目源代码和打包的jar包,jar包测试可以直接调用)
【出现的问题记录】打成jar包后只能把jar包和待转换的word文档放在同一个目录下,并且生成的目录也只能放在同一个目录下,这和Java中getResourceAsStream的用法有关系:
getResourceAsStream读取的文件路径只局限与工程的源文件夹中,包括在工程src根目录下,以及类包里面任何位置,但是如果配置文件路径是在除了源文件夹之外的其他文件夹中时,该方法是用不了的。
引用自:https://www.iteye.com/blog/riddickbryant-436693
【已解决,封装jar包后读取项目目录外的文件】
之前打开word的文件的方法是利用getResourceAsStream:
file_path = "C:\\Users\\16616\\Desktop\\XXX.docx";
word = TestWord.class.getClassLoader().getResourceAsStream(file_path);
Document doc = new Document(word);
现在直接用new Document打开:
Document doc = new Document(file_path);
最后是源代码:
package com.demo;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.stream.Stream;
import com.aspose.words.Document;
import com.aspose.words.FileFormatUtil;
import com.aspose.words.License;
import com.aspose.words.SaveFormat;
/**
*
* 由于ASPOSE比较吃内存,操作大一点的文件就会堆溢出,所以请先设置好java虚拟机参数:-Xms512m -Xmx512m(参考值)
* 如有疑问,请在CSDN下载界面留言,或者联系QQ569925980
*
* @author Spark
*
*/
public class TestWord {
private static InputStream license;
private static InputStream word;
/**
* 获取license
*
* @return
*/
public static boolean getLicense() {
boolean result = false;
try {
license = TestWord.class.getClassLoader().getResourceAsStream("license.xml");// license路径
// word = TestWord.class.getClassLoader().getResourceAsStream("\\4-广州.doc");
License aposeLic = new License();
aposeLic.setLicense(license);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public static void word2pdf(String file_path,String save_path) {
// word = TestWord.class.getClassLoader().getResourceAsStream("\\XXX.doc");// 原始word路径
word = TestWord.class.getClassLoader().getResourceAsStream(file_path);
// 验证License
if (!getLicense()) {
return;
}
try {
long old = System.currentTimeMillis();
// Document doc = new Document(word);
Document doc = new Document(file_path);
// File file = new File("C:\\Users\\16616\\Desktop\\AsposeWord\\src\\test.pdf");// 输出路径
//存为新PDF文件,文件名需要从file_path中提取出来
File tempFile =new File(file_path.trim());
String fileName = tempFile.getName();
System.out.println("fileName = " + fileName);
String[] tmp = fileName.split("\\.");
String pdf_name = tmp[0]+".pdf";
System.out.println("pdfName = "+ pdf_name);
File file = new File(save_path+"/"+pdf_name);
FileOutputStream fileOS = new FileOutputStream(file);
doc.save(fileOS, SaveFormat.PDF);
long now = System.currentTimeMillis();
System.out.println("共耗时:" + ((now - old) / 1000.0) + "秒\n\n" + "文件保存在:" + file.getPath());
} catch (Exception e) {
e.printStackTrace();
}
}
/**
*
* @param args
*/
public static void main(String[] args) {
String file_path = args[0];
String save_path = args[1];
word2pdf(file_path,save_path);
// word2pdf("C:\\Users\\16616\\Desktop\\XXX.docx","C:/Users/16616/Desktop");
}
}
将含有第三方jar包的Java项目打包,并且使用命令行进行jar包的传参调用:
1.首先,Eclipse将已经含有第三方jar包的项目打包的方法:
选File/Export…然后Java/Runnable JAR file,然后选要运行的有main()的类,选extract required libraries into generated JAR。
2.找到打包后的文件,将待转换的word文件放到jar包的同级目录下,如果想要将转换后的PDF文件放到word文件的同级:
命令行调用jar包方法:
java -jar word2pdf.jar [路径下的word文件名][PDF目标路径]
最后会在该文件夹下生成一个pdfed.pdf文件。
附:如何命令行传参调用java项目(或在bat文件中调用)
1、无参
打开jar包所在目录,输入 java -jar xxx.jar
2、有参
打开jar包所在目录 输入 java -jar xxx.jar 参数1 参数2 ……(参数间用空格隔开)
对应main函数中的:
public static void main(String[] args) {
String sourcePath = args[0];// 参数1
String targetPath = args[1];// 参数2
}
项目的源代码和jar包以及使用方法已经放在了公众号下,后台回复关键词【word2pdf】即可获取。
[1] how-to-convert-word-doc-to-pdf-in-linux
[2] 将java项目导出为jar包+导出第三方jar包+使用命令行调用+传参
[3] aspose-words-15.8.0 完美解决word转pdf
[4] 怎样把引用的jar包和本项目一起导出成jar文件