word转pdf是一个比较老的话题了,网上有各种各样的版本,经过了各种尝试,主要是在linux和windows平台运行,有通过脚本的,有通过代码的,这些方法效果各异。
一、openoffice和libreoffice
这两个是开源软件,libreoffice是openoffice的一个分支,两个软件的表现,只能说是中规中矩,如果样式不是很多,且对样式没有很高的要求,还是基本满足要求的。它们两个在word转pdf的时候,一些样式是和Microsoft office是不兼容的,还有一些计算公式也要小心使用(比如一些页眉和页脚的计算)。
libreoffice的安装:安装过程
openoffice的安装和使用:openoffice安装使用
openoffice的临时启动:
/opt/openoffice4/program/soffice -headless -accept=”socket,host=127.0.0.1,port=8100;urp;” -nofirststartwizard
openoffice的永久启动:
nohup /opt/openoffice4/program/soffice -headless -accept=”socket,host=127.0.0.1,port=8100;urp;” -nofirststartwizard &
然后查看是否启动完成:ps -ef|grep openoffice
查看默认端口8100:netstat -lnp |grep 8100
解决中文乱码问题:解决中文乱码
主要思路:乱码的主要原因是字体的不识别,所以将windows的字体拷贝到linux
word转pdf的思路,有两条:1、将linux命令写入到代码中 2、用代码启动openoffice服务进行转换
1、命令方式:参考链接:DocumentConvert.py+Openoffice方式
2、代码方式,参考链接:java+OpenOffice+JodConverter方式
二、Apache的wordConverterToPdf方式进行转换
这种方式的转换,比较麻烦,而且样式的支持不好。
package pageOffice.utils;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections4.MapUtils;
import org.apache.poi.xwpf.converter.core.utils.StringUtils;
import org.apache.poi.xwpf.converter.pdf.PdfConverter;
import org.apache.poi.xwpf.converter.pdf.PdfOptions;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
public class WordPdfUtils {
public static void main(String[] args) throws Exception {
// String filepath = "xxxx.docx";
String filepath = "xxxx.doc";
String outpath = "xxxx.pdf";
InputStream source = new FileInputStream(filepath);
OutputStream target = new FileOutputStream(outpath);
Map<String, String> params = new HashMap<String, String>();
PdfOptions options = PdfOptions.create();
wordConverterToPdf(source, target, options, params);
}
/**
* 将word文档, 转换成pdf, 中间替换掉变量
*
* @param source
* 源为word文档, 必须为docx文档
* @param target
* 目标输出
* @param params
* 需要替换的变量
* @throws Exception
*/
public static void wordConverterToPdf(InputStream source, OutputStream target, Map<String, String> params)
throws Exception {
wordConverterToPdf(source, target, null, params);
}
/**
* 将word文档, 转换成pdf, 中间替换掉变量
*
* @param source
* 源为word文档, 必须为docx文档
* @param target
* 目标输出
* @param params
* 需要替换的变量
* @param options
* PdfOptions.create().fontEncoding( "windows-1250" ) 或者其他
* @throws Exception
*/
public static void wordConverterToPdf(InputStream source, OutputStream target, PdfOptions options,
Map<String, String> params) throws Exception {
XWPFDocument doc = new XWPFDocument(source);
paragraphReplace(doc.getParagraphs(), params);
for (XWPFTable table : doc.getTables()) {
for (XWPFTableRow row : table.getRows()) {
for (XWPFTableCell cell : row.getTableCells()) {
paragraphReplace(cell.getParagraphs(), params);
}
}
}
PdfConverter.getInstance().convert(doc, target, options);
}
/** 替换段落中内容 */
private static void paragraphReplace(List<XWPFParagraph> paragraphs, Map<String, String> params) {
if (MapUtils.isNotEmpty(params)) {
for (XWPFParagraph p : paragraphs) {
for (XWPFRun r : p.getRuns()) {
String content = r.getText(r.getTextPosition());
if (StringUtils.isNotEmpty(content) && params.containsKey(content)) {
r.setText(params.get(content), 0);
}
}
}
}
}
}
三、SaveAsPDFandXPS + jacob.jar + jacob.dll
效果最好的一种方法,但是需要 window 环境,而且速度是最慢的需要安装 msofficeWord 以及 SaveAsPDFandXPS.exe,这种方式目前还没有找到能够在linux上运行的版本
代码如下:
import java.io.File;
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
/**
* 效果最好的一种方法,但是需要 window 环境,而且速度是最慢的需要安装 msofficeWord 以及 SaveAsPDFandXPS.exe (
* word 的一个插件,用来把 word 转化为 pdf,可以不用安装,本次未安装测试通过 )
*
* SaveAsPDFandXPS
* 下载地址:http://www.microsoft.com/zh-cn/download/details.aspx?id=7
* jacob 包下载地址:http://sourceforge.net/projects/jacob-project/
*
* jacob.jar 放在 E:\jdk1.5.0_14\jre\lib\ext
* jacob.dll 放在 E:\jdk1.5.0_14\jre\bin
*
* @author u Y
*
*/
public class WordToPdf {
private static final int wdFormatPDF = 17; // PDF 格式
public void wordToPDF(String sfileName, String toFileName) {
System.out.println("启动 Word...");
long start = System.currentTimeMillis();
ActiveXComponent app = null;
Dispatch doc = null;
try {
app = new ActiveXComponent("Word.Application");
app.setProperty("Visible", new Variant(false));
Dispatch docs = app.getProperty("Documents").toDispatch();
doc = Dispatch.call(docs, "Open", sfileName).toDispatch();
System.out.println("打开文档..." + sfileName);
System.out.println("转换文档到 PDF..." + toFileName);
File tofile = new File(toFileName);
if (tofile.exists()) {
tofile.delete();
}
Dispatch.call(doc, "SaveAs", toFileName, // FileName
wdFormatPDF);
long end = System.currentTimeMillis();
System.out.println("转换完成..用时:" + (end - start) + "ms.");
} catch (Exception e) {
System.out.println("========Error:文档转换失败:" + e.getMessage());
} finally {
Dispatch.call(doc, "Close", false);
System.out.println("关闭文档");
if (app != null)
app.invoke("Quit", new Variant[] {});
}
// 如果没有这句话,winword.exe进程将不会关闭
ComThread.Release();
}
public static void main(String[] args) {
WordToPdf d = new WordToPdf();
d.wordToPDF("E://test.doc", "E://test.pdf");
}
}
四:AsposeWord方式
该方式是重点推出的方式,效果好,而且跨平台,但是不是开源的,但网上也有一些绿色版本,大家在选择版本的时候,可以先试用,看看效果,然后再选择相应的版本,因为最新的版本可能不稳定,在测试过程中,最新版本转换pdf的时候出现空指针错误,有可能是新版本对样式的转换出现问题,目前比较好的版本是17开头的。
试用版和正式版的最大区别就是:试用版会有水印,而正式版没有
代码很简单的几行:
package pageOffice.utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import com.aspose.words.Document;
import com.aspose.words.License;
import com.aspose.words.SaveFormat;
/**
* @author Administrator
* @version $Id$
* @since
* @see
*/
public class Word2PdfUtil {
public static void main(String[] args) {
doc2pdf("E:/test.doc","E:/ttt.pdf");
}
public static boolean getLicense() {
boolean result = false;
try {
File file = new File("E:\\license.xml"); // 新建一个空白pdf文档
InputStream is = new FileInputStream(file); // license.xml应放在..\WebRoot\WEB-INF\classes路径下
License aposeLic = new License();
aposeLic.setLicense(is);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public static void doc2pdf(String inPath, String outPath) {
if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
return;
}
try {
long old = System.currentTimeMillis();
File file = new File(outPath); // 新建一个空白pdf文档
FileOutputStream os = new FileOutputStream(file);
Document doc = new Document(inPath); // Address是将要被转化的word文档
doc.save(os, SaveFormat.PDF);// 全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF,
// EPUB, XPS, SWF 相互转换
long now = System.currentTimeMillis();
System.out.println("共耗时:" + ((now - old) / 1000.0) + "秒"); // 转化用时
} catch (Exception e) {
e.printStackTrace();
}
}
}
license.xml的下载:license.xml
jar包的下载:aspose-words-15.8.0.jar
没有积分的童鞋可以留邮箱私发哦~
五、采用第三方技术 IText、Poi、Jsoup
该方法的思路是,先将word转换成html,然后再将html转换为pdf,先不说该思路实现起来麻烦,有点曲线救国的意思,但是难以掌控的是样式的转换,转换了两次还能够保持一样吗,上面那些方法都是转换一次,都很难保证一致,更不用说这个转换两次的了,所以不太看好。
写到这里,相信很多人也明白了,最好的两种方式是第三种和第四种,尤其是Aspose-word,可以跨平台,但它是商用软件。一开始被看好的开源的office,在一些普通的样式里面是够用了,但是一些复杂的样式,与Microsoft office的样式不兼容的时候,会出现转换的差异,尤其是对不同的编辑软件的兼容性也很不好,比如用Microsoft office和WPS编辑之后,转换出来的结果也不一样。要求不是特别高的,还是可以尝试此方案的。如果有windows服务器,可以将第三种方式:SaveAsPDFandXPS + jacob.jar + jacob.dll 做成工具包,提供给其他服务器进行调用,这样也是可以的。
完成这个功能的时候,走了特别多的弯路,希望在看这篇文章的你,能够结合这篇文章少走一些弯路。