最近,公司要求做個文件轉pdf的調研報告,於是在網上找了一些實現方法,現在將這些方法做個對比,並記錄下來,以後或許有用呢,哈哈。
首先說一下需求,產品要求不能使用第三方軟件實現,因爲這種實現方式效率不高,所以需要使用“純Java代碼”實現。同時也對跨平臺有要求,系統需要運行在linux系統上。綜合現階段發現的方案,決定採用基於Aspose的方式進行實現。
好了,現在先看一下對比的結果:
各實現對比表
於Windows平臺進行測試:
測試文件:
Word:大小380k、頁數225頁。內含圖片(排版),文字(不同顏色、字體、不同語言)、表格(含樣式)
Excel:大小297k。內含插入圖形、長表格。
PPT:大小539k、內含圖片、自定義圖形、文字(不同顏色、字體、不同語言)、表格(含樣式)
|
基於Openoffice |
基於libreOffice |
基於Office |
基於Pio+Itext |
基於Aspose |
|
跨平臺性 |
跨平臺 |
跨平臺 |
僅Windows |
跨平臺 |
跨平臺 |
|
是否安裝軟件 |
需安裝Openoffice |
需安裝libreOffice |
需安裝Microsoft Office |
否 |
否 |
|
是否收費 |
免費 |
免費 |
軟件收費 (可破解) |
免費 |
Jar包收費 (可破解) |
|
轉換Word |
效率 |
未測 |
首次開啓14s。 平均8s |
平均10s |
平均10s |
平均4.2s |
效果 |
未測 |
支持不同字體、不同文字、支持表格樣式。 插入圖形走樣 轉換後頁數相當 (225-227) 大小相當 (380k-360k) |
完全一致 轉換後大小上升 (380k-1.24M) |
字體、表格樣式、插入圖形失真。(嚴重失真) 轉換後頁數下降 (225-105) 大小飆升 (380k-1.74M) |
字體樣式或無法轉換。 轉換後頁數相當(225-224) 大小上升 (380k-721k) |
|
轉換Excel |
效率 |
未測 |
首次開啓10s 平均4.5s |
異常(Office2016) |
平均5.8s |
平均2.6s |
效果 |
未測 |
支持文本顏色。 不支持插入圖形 文本會發生走樣 轉換後大小相當 (297k-140k) |
提示異常 (Office 2016) |
樣式失真。 excel頁面大小過長導致PDF頁面被截斷,無法顯示完整 |
不支持插入圖片轉換 轉換後大小減小 (297k-196k) |
|
轉換PPT |
效率 |
未測 |
平均5.3s |
平均4s |
平均15s |
平均15.5s |
效果 |
未測 |
幾乎完全一致 能完美支持表格、自定義圖形、圖片、文字等 大小減小 (539k-255k) |
轉換成功,無法打開(Office 2016) |
樣式嚴重失真。甚至錯誤。 轉換後大小上升 (539K-1.3M) 頁數 (225-105) |
幾乎完全一致 轉換後大小減小 (539k-398k) |
|
優點 |
跨平臺 |
文檔轉換失真小。 跨平臺 |
轉化相對快。對於Office能很好保證少失真,特別是Word文檔 |
跨平臺 |
轉換速度快。 支持跨平臺。 不需要安裝軟件。 失真情況較小 |
|
缺點 |
需要安裝額外軟件 |
需要安裝額外軟件、效率較低 |
不跨平臺 需安裝Office Office收費 Office版本不同效果不同(不穩定性) 對JDK有污染 |
樣式失真特別嚴重、效率極低。 技術複雜 |
收費(但是可以破解)、即使付費,也不提供源碼(官網) |
|
評價 |
未知 |
穩定 |
差 |
極差 |
好 |
結論
使用Aspose效果最好。
各種技術實現起來,綜合來說Aspose是比較好的方案,唯一的弊端就是收費。
下面介紹各種方案的具體實現,以及其優缺點,效果圖。
1)基於openoffice(跨平臺、需安裝openoffice、複雜格式有錯位)
原理:
通過第三方工具openoffice,將word、excel、ppt、txt等文件轉換爲pdf文件
先安裝openoffice軟件(Windows或Linux有提供軟件)
使用JODConverter的Java的OpenDocument 文件轉換器API操作Office系列文件轉換爲PDF文件
優點:
轉換效果比較好。是比較主流的做法
缺點:
服務器需要安裝openoffice,比較負重
具體實現:
1.下載安裝軟件
1)Openoffice:Apache下的一個開放免費的文字處理軟件
下載地址:http://www.openoffice.org/zh-cn/download/
2)JODConverter一個Java的OpenDocument 文件轉換器,只用到它的jar包
下載地址:https://sourceforge.net/projects/jodconverter/files/JODConverter/
2.啓動服務:
打開dos窗口,進入openoffice安裝盤符,輸入以下代碼來啓動服務:
soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard
3.Java實現操作轉化:
Pom.xml依賴
<!-- https://mvnrepository.com/artifact/com.artofsolving/jodconverter-maven-plugin -->
<dependency>
<groupId>com.artofsolving</groupId>
<artifactId>jodconverter-maven-plugin</artifactId>
<version>2.2.1</version></dependency>
</dependency>
轉換工具:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ConnectException;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.artofsolving.jodconverter.DocumentConverter;
import com.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.converter.OpenOfficeDocumentConverter;
/**
* 利用jodconverter(基於OpenOffice服務)將文件(*.doc、*.docx、*.xls、*.ppt)轉化爲html格式或者pdf格式,
* 使用前請檢查OpenOffice服務是否已經開啓, OpenOffice進程名稱:soffice.exe | soffice.bin
*/
public class Doc2HtmlUtil {
private static Doc2HtmlUtil doc2HtmlUtil;
/** * 獲取Doc2HtmlUtil實例 */
public static synchronized Doc2HtmlUtil getDoc2HtmlUtilInstance() {
if (doc2HtmlUtil == null) {
doc2HtmlUtil = new Doc2HtmlUtil();
}
return doc2HtmlUtil;
}
/*** 轉換文件成pdf */
public String file2pdf(InputStream fromFileInputStream, String toFilePath,String type) throws IOException {
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
String timesuffix = sdf.format(date);
String docFileName = null;
String htmFileName = null;
if(".doc".equals(type)){
docFileName = "doc_" + timesuffix + ".doc";
htmFileName = "doc_" + timesuffix + ".pdf";
}else if(".docx".equals(type)){
docFileName = "docx_" + timesuffix + ".docx";
htmFileName = "docx_" + timesuffix + ".pdf";
}else if(".xls".equals(type)){
docFileName = "xls_" + timesuffix + ".xls";
htmFileName = "xls_" + timesuffix + ".pdf";
}else if(".ppt".equals(type)){
docFileName = "ppt_" + timesuffix + ".ppt";
htmFileName = "ppt_" + timesuffix + ".pdf";
}else{
return null;
}
File htmlOutputFile = new File(toFilePath + File.separatorChar + htmFileName);
File docInputFile = new File(toFilePath + File.separatorChar + docFileName);
if (htmlOutputFile.exists())
htmlOutputFile.delete();
htmlOutputFile.createNewFile();
if (docInputFile.exists())
docInputFile.delete();
docInputFile.createNewFile();
/*** 由fromFileInputStream構建輸入文件 */
try {
OutputStream os = new FileOutputStream(docInputFile);
int bytesRead = 0;
byte[] buffer = new byte[1024 * 8];
while ((bytesRead = fromFileInputStream.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.close();
fromFileInputStream.close();
} catch (IOException e) {
}
// 連接服務
OpenOfficeConnection connection = new SocketOpenOfficeConnection(8100);
try {
connection.connect();
} catch (ConnectException e) {
System.err.println("文件轉換出錯,請檢查OpenOffice服務是否啓動。");
}
// convert 轉換
DocumentConverter converter = new OpenOfficeDocumentConverter(connection);
converter.convert(docInputFile, htmlOutputFile);
connection.disconnect();
// 轉換完之後刪除word文件
docInputFile.delete();
return htmFileName;
}
public static void main(String[] args) throws IOException {
Doc2HtmlUtil coc2HtmlUtil = getDoc2HtmlUtilInstance ();
File file = null;
FileInputStream fileInputStream = null;
file = new File("C:/Users/MACHENIKE/Desktop/xxx.doc");
fileInputStream = new FileInputStream(file);
coc2HtmlUtil.file2pdf(fileInputStream, "E:/360","doc");
}
}
簡易實現:
public void createPdf(String docFileName) throws IOException{
String path = this.getSession().getServletContext().getRealPath("/")+"attachment/";
File inputFile = new File(path+"/doc/"+ docFileName + ".doc");
File outputFile = new File(path+"/pdf/"+docFileName + ".pdf");
// connect to an OpenOffice.org instance running on port 8100
OpenOfficeConnection connection = new SocketOpenOfficeConnection(8100);
connection.connect();
// convert
DocumentConverter converter = new OpenOfficeDocumentConverter(connection);
converter.convert(inputFile, outputFile);
// close the connection
connection.disconnect();
}
效果:(略)
2)基於libreoffice(跨平臺、需安裝libreoffice)
原理:
通過第三方工具libreoffice,將word、excel、ppt、txt等文件轉換爲pdf文件
先安裝libreoffice軟件(Windows或Linux有提供軟件)
使用JODConverter的Java的OpenDocument 文件轉換器API操作Office系列文件轉換爲PDF文件
優點:
轉換效果比較好。是比較主流的做法
缺點:
服務器需要安裝libreoffice,比較負重。啓動服務時效率不是很高
具體實現:
1.下載安裝軟件
1)Openoffice:Apache下的一個開放免費的文字處理軟件
下載地址:http://www.openoffice.org/zh-cn/download/
2)JODConverter一個Java的OpenDocument 文件轉換器,只用到它的jar包
下載地址:https://sourceforge.net/projects/jodconverter/files/JODConverter/
2.Java實現
依賴:
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.0</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-pdfa</artifactId>
<version>5.5.0</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.0</version>
</dependency>
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-local</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf</artifactId>
<version>9.0.7</version>
</dependency>
轉換
public class LibreOfficeAndJodconverter {
private static OfficeManager officeManager = null;
private static final String dirPath = "F:/pdf/";
private static final String LibreOfficeDirPath = "D:/LibreOffice6.1.1.2/LibreOffice";
public static void init() {
try {
System.out.println("嘗試連接已啓動的服務...");
ExternalOfficeManagerConfiguration externalProcessOfficeManager = new ExternalOfficeManagerConfiguration();
externalProcessOfficeManager.setConnectOnStart(true);
externalProcessOfficeManager.setPortNumber(8100);
officeManager = externalProcessOfficeManager.buildOfficeManager();
officeManager.start();
System.out.println("轉換服務啓動成功!");
} catch (Exception e) {
//命令方式:soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard
System.out.println("啓動新服務!");
String libreOfficePath = LibreOfficeDirPath;
// 此類在jodconverter-core中3版本中存在,在2.2.2版本中不存在
DefaultOfficeManagerConfiguration configuration = new DefaultOfficeManagerConfiguration();
// libreOffice的安裝目錄
configuration.setOfficeHome(new File(libreOfficePath));
// 設置端口號
configuration.setPortNumber(8100);
// 設置任務執行超時爲5分鐘
configuration.setTaskExecutionTimeout(1000 * 60 * 5L);
// 設置任務隊列超時爲24小時
configuration.setTaskQueueTimeout(1000 * 60 * 60 * 24L);
// 開啓轉換服務
officeManager = configuration.buildOfficeManager();
officeManager.start();
System.out.println("服務啓動成功!");
}
}
public static void desory() {
if (officeManager != null) {
officeManager.stop();
}
}
/** * 合併多個PDF,注意,源pdf中不能含有目的pdf,否則將合併失敗*/
public static boolean mergePdfFiles(String[] files, String newfile) {
boolean retValue = false;
Document document = null;
try {
document = new Document(new PdfReader(files[0]).getPageSize(1));
PdfCopy copy = new PdfCopy(document, new FileOutputStream(newfile));
document.open();
for (int i = 0; i < files.length; i++) {
PdfReader reader = new PdfReader(files[i]);
int n = reader.getNumberOfPages();
for (int j = 1; j <= n; j++) {
document.newPage();
PdfImportedPage page = copy.getImportedPage(reader, j);
copy.addPage(page);
}
}
retValue = true;
} catch (Exception e) {
e.printStackTrace();
} finally {
document.close();
}
return retValue;
}
/**
* 開啓服務時耗時,需要安裝
* 並不是看到什麼,就轉化爲什麼樣的。有偏移
*
* @param args
*/
public static void main(String[] args) {
init();
task();
desory();
}
public static void task() {
String outputname = "output.pdf";
doDocToFdpLibre("test.docx", outputname);
doDocToFdpLibre("ppt.pptx", outputname);
doDocToFdpLibre("放棄.xlsx", outputname);
doDocToFdpLibre("1.txt", outputname);
doDocToFdpLibre("不老夢.jpg", outputname);
}
public static String doDocToFdpLibre(String inputFileName, String outputFileName) {
File inputFile = new File("F:/pdf/" + inputFileName);
System.out.println("libreOffice開始轉換..............................");
Long startTime = System.currentTimeMillis();
OfficeDocumentConverter converter = new OfficeDocumentConverter(officeManager);
File outputFile = new File(dirPath + outputFileName);
if (outputFile.exists()) {
String uuid1 = UUID.randomUUID().toString();
File temp1 = new File(dirPath + uuid1 + ".pdf");
outputFile.renameTo(temp1);
String uuid = UUID.randomUUID().toString();
File temp2 = new File(dirPath + uuid + ".pdf");
converter.convert(inputFile, temp2);
String[] files = {dirPath + uuid1 + ".pdf", dirPath + uuid + ".pdf"};
String savepath = dirPath + outputFileName;
if (mergePdfFiles(files, savepath)) {
temp1.delete();
temp2.delete();
}
} else {
converter.convert(inputFile, outputFile);
}
// 轉換結束
System.out.println("轉換結束。。。。。");
//轉換時間
long endTime = System.currentTimeMillis();
long time = endTime - startTime;
System.out.println("libreOffice轉換所用時間爲:" + time);
return outputFile.getPath();
}
}
效果:
Word文檔
除去剛開啓,平均8s
libreOffice轉換所用時間爲:14044ms
libreOffice轉換所用時間爲:7147ms
libreOffice轉換所用時間爲:6886ms
libreOffice轉換所用時間爲:7176ms
libreOffice轉換所用時間爲:7001ms
libreOffice轉換所用時間爲:8397ms
libreOffice轉換所用時間爲:8141ms
Excel
libreOffice轉換所用時間爲:10584ms
libreOffice轉換所用時間爲:4534ms
libreOffice轉換所用時間爲:4453ms
libreOffice轉換所用時間爲:4369ms
ppt轉換
libreOffice轉換所用時間爲:59257ms
libreOffice轉換所用時間爲:52320ms
libreOffice轉換所用時間爲:52571ms
3)基於Microsofe Office(僅Windows、需安裝Microsoft Office)
原理:
類似於Microsoft Office的“另存爲”操作。用Jacob實現對Office系列文件的轉換(用jacob(Java COM Bridge)操作office的方式)
需要在Windows下安裝Microsoft Office,使用jacob操作Office文件,
並把jacob-x.xx-x64.dll放到java/bin(與java.exe相同)目錄下
優點:
能很好的轉換,失真小(完美保持原doc格式)
缺點:
1需要安裝Microsoft Office。
2需要把jacob-x.xx-x64.dll放到java/bin(與java.exe相同)目錄下,對JDK目錄有污染。
3不支持跨平臺
4. Microsoft Office版本不同可能影響轉換是否成功
具體實現
1.下載jacob包並加入到環境中:
Pom:
<!-- https://mvnrepository.com/artifact/com.hynnet/jacob -->
<dependency>
<groupId>com.hynnet</groupId>
<artifactId>jacob</artifactId>
<version>1.18</version>
</dependency>
2.將jacob包的dll導入到jdk/jre/bin下
(不放會報錯:java.lang.NoClassDefFoundError: Could not initialize class com.jacob.com.Dispatch)
或指定路徑:System.getProperty("java.library.path");
3.轉換方法:
public class Jacob {
/** 轉PDF格式值 */
static final int WORD_FORMAT_PDF = 17;
static final int EXCEL_FORMAT_PDF = 0;
static final int PPT_FORMAT_PDF = 32;
/*** @Description:根據文件類型轉換爲pdf */
public static void convert2PDF(String inputFile, String pdfFile) {
String suffix = getFileSufix(inputFile);
if (suffix.equals("doc") || suffix.equals("docx") || suffix.equals("txt")) {
word2PDF(inputFile, pdfFile);
} else if (suffix.equals("xls") || suffix.equals("xlsx")) {
excel2PDF(inputFile, pdfFile);
} else if (suffix.equals("ppt") || suffix.equals("pptx")) {
ppt2PDF(inputFile, pdfFile);
} else {
System.out.println("文件格式不支持轉換!");
}
}
/** * @Description:word轉pdf */
private static void word2PDF(String inputFile, String pdfFile) {
System.out.println("啓動Word...");
long start = System.currentTimeMillis();
ActiveXComponent app = null;
Dispatch doc = null;
try {
// 創建一個word對象
app = new ActiveXComponent("Word.Application");
// 不可見打開word (但默認是不可見的)
app.setProperty("Visible", new Variant(false));
// 獲取文擋屬性
// 調用Documents對象中Open方法打開文檔,並返回打開的文檔對象Document
Dispatch docs = app.getProperty("Documents").toDispatch();
doc = Dispatch.call(docs, "Open", inputFile).toDispatch();
System.out.println("打開文檔..." + inputFile);
System.out.println("轉換文檔到PDF..." + pdfFile);
File tofile = new File(pdfFile);
if(tofile.exists()) {
tofile.delete();
}
// word保存爲pdf格式宏,值爲17
Dispatch.call(doc, "SaveAs", pdfFile, WORD_FORMAT_PDF);
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();
}
/** * @Description:excel轉pdf */
private static void excel2PDF(String inputFile, String pdfFile) {
System.out.println("啓動Excel...");
long start = System.currentTimeMillis();
ActiveXComponent app = null;
Dispatch excel = null;
try {
// 創建一個excel對象
app = new ActiveXComponent("Excel.Application");
// 不可見打開excel
app.setProperty("Visible", new Variant(false));
// 獲取文擋屬性
Dispatch excels = app.getProperty("Workbooks").toDispatch();
// 調用Documents對象中Open方法打開文檔,並返回打開的文檔對象Document
excel = Dispatch.call(excels, "Open", inputFile).toDispatch();
System.out.println("打開文檔..." + inputFile);
System.out.println("轉換文檔到PDF..." + pdfFile);
File tofile = new File(pdfFile);
if(tofile.exists()) {
tofile.delete();
}
// Excel不能調用SaveAs方法
Dispatch.call(excel, "ExportAsFixedFormat", EXCEL_FORMAT_PDF, pdfFile);
long end = System.currentTimeMillis();
System.out.println("轉換完成..用時:" + (end - start) + "ms.");
} catch (Exception e) {
System.out.println("========Error:文檔轉換失敗:" + e.getMessage());
} finally {
Dispatch.call(excel, "Close", false);
System.out.println("關閉文檔");
if (app != null)
app.invoke("Quit", new Variant[] {});
}
//如果沒有這句話,winword.exe進程將不會關閉
ComThread.Release();
}
/*** @Description:ppt轉pdf */
private static void ppt2PDF(String inputFile, String pdfFile) {
System.out.println("啓動PPT...");
long start = System.currentTimeMillis();
ActiveXComponent app = null;
Dispatch ppt = null;
try {
// 創建一個ppt對象
app = new ActiveXComponent("PowerPoint.Application");
// 不可見打開(PPT轉換不運行隱藏,所以這裏要註釋掉)
// app.setProperty("Visible", new Variant(false));
// 獲取文擋屬性
Dispatch ppts = app.getProperty("Presentations").toDispatch();
// 調用Documents對象中Open方法打開文檔,並返回打開的文檔對象Document
ppt = Dispatch.call(ppts, "Open", inputFile, true, true, false).toDispatch();
System.out.println("打開文檔..." + inputFile);
System.out.println("轉換文檔到PDF..." + pdfFile);
File tofile = new File(pdfFile);
if(tofile.exists()) {
tofile.delete();
}
Dispatch.call(ppt, "SaveAs", pdfFile, PPT_FORMAT_PDF);
long end = System.currentTimeMillis();
System.out.println("轉換完成..用時:" + (end - start) + "ms.");
} catch (Exception e) {
System.out.println("========Error:文檔轉換失敗:" + e.getMessage());
} finally {
Dispatch.call(ppt, "Close");
System.out.println("關閉文檔");
if (app != null)
app.invoke("Quit", new Variant[] {});
}
//如果沒有這句話,winword.exe進程將不會關閉
ComThread.Release();
}
/*** @Description:獲取文件後綴*/
private static String getFileSufix(String fileName) {
int splitIndex = fileName.lastIndexOf(".");
return fileName.substring(splitIndex + 1);
}
}
效果:
word文檔
成功:用時10821ms
成功:用時9865ms
成功:用時9867ms
成功:用時10481ms
excel:
ppt
成功:用時5265ms
成功:用時3885ms
成功:用時3788ms
成功:用時3817ms
原因探究
報錯的原因主要是:office版本問題。開發的時候使用的office2013,PPT不能轉pdf。在服務器上安裝的office2007,出現了PPT可以轉成PDF,excel不能轉pdf。卸載了office2007安裝office2010後出現了excel能轉PDF,PPT不能轉PDF。office的版本問題中,world文檔不管什麼版本都可以成功的轉pdf。最後解決的辦法:安裝2007的excel,2010的PPT,world就能成功的轉pdf。注意:office2007不能轉pdf,需要安裝一個插件。
4)POI+IText方式(跨平臺、效果差、效率低)
原理:
用 poi 將word轉換成 html
用IText 將html轉換成pdf(要求html中所有標籤都必須要閉合,所以這裏用jsoup對html進行轉換)
優點:
不需要安裝軟件、跨平臺
缺點:
- 失真問題比較大。(格式兼容差)
- 涉及到中文編碼問題。
- 效率比較低
具體實現
public static String officeToHtml(String sourcePath,String targetPath){
String ext = FileUtils.getFileExt(sourcePath).toLowerCase();
String result = null;
switch (ext){
case Consts.OFFICE.DOC:
case Consts.OFFICE.DOCX:
result = POIWordToHtml.wordToHtml(sourcePath, wordImagePath, targetPath);
break;
case Consts.OFFICE.XLS:
case Consts.OFFICE.XLSX:
result = POIExcelToHtml.excelToHtml(sourcePath,targetPath, true);
break;
case Consts.OFFICE.PPT:
case Consts.OFFICE.PPTX:
POIPptToHtml.pptToHtml(sourcePath,targetPath);
break;
default:
}
return result;
}
具體工具類暫略
具體工具類暫略 |
注意事項:
注意:IText 根據html生成文件的是否會驗證html文件是否標準,例如通過poi轉換的出來的html文件的一些標籤會缺少標籤閉合 ,
如果用這種html進行轉換是沒有辦法通過itext 的校驗的。會出現以下異常
錯誤: “The element type "meta" must be terminated by the matching end-tag "</meta>".”
org.xhtmlrenderer.util.XRRuntimeException: Can't load the XML resource (using TRaX transformer). org.xml.sax.SAXParseException: The element type "meta" must be terminated by the matching end-tag "</meta>". 。
html不規範可採用第三方 jar 包 Jsoup, 直接調用parse方法讓html標準
相關博客:
java 實現word 轉PDF (採用第三方技術 IText、Poi、Jsoup)
效果(很差):
Word:
耗時大概平均10s左右
耗時:10832ms
耗時:8788ms
耗時:9035ms
耗時:8827ms
Ppt:
平均大概15s左右
耗時:15932ms
耗時:14835ms
耗時:14884ms
耗時:14889ms
Excel:
平均5.8s
耗時:6263ms
耗時:5858ms
耗時:5698ms
耗時:5546ms
5)Aspose實現(跨平臺、付費)
優點:
比較完美,低失真。
缺點:
不跨平臺、不免費
具體實現:
下載相應jar包。(若不是付費版,將出現水印,限制頁數等情況)
Word:
public static boolean getLicense() {
boolean result = false;
try {
InputStream is = new FileInputStream(new File("E:\\IDEA2017\\something2pdf-demo\\src\\main\\resources\\license.xml")); // 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 Address) {
if (!getLicense()) { // 驗證License 若不驗證則轉化出的pdf文檔會有水印產生
return;
}
try {
long old = System.currentTimeMillis();
File file = new File("F:\\pdf/pdf1.pdf"); //新建一個空白pdf文檔
FileOutputStream os = new FileOutputStream(file);
Document doc = new Document(Address); //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();
}
}
Excel
public static boolean getLicense() {
boolean result = false;
try {
InputStream is = Excel2Pdf.class.getClassLoader().getResourceAsStream("xlsxlicense.xml"); // 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 excel2pdf(String Address) {
if (!getLicense()) { // 驗證License 若不驗證則轉化出的pdf文檔會有水印產生
return;
}
try {
long old = System.currentTimeMillis();
File file = new File("F:\\pdf/pdf2.pdf");// 輸出路徑
Workbook wb = new Workbook(Address);// 原始excel路徑
FileOutputStream fileOS = new FileOutputStream(file);
wb.save(fileOS, SaveFormat.PDF);
fileOS.close();
long now = System.currentTimeMillis();
System.out.println("共耗時:" + ((now - old) / 1000.0) + "秒\n\n" + "文件保存在:" + file.getPath()); //轉化過程耗時
} catch (Exception e) {
e.printStackTrace();
}
}
Ppt
public static boolean getLicense() {
boolean result = false;
try {
license = Ppt2Pdf.class.getClassLoader().getResourceAsStream("pptlicense.xml");// license路徑
License aposeLic = new License();
aposeLic.setLicense(license);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public static void ppt2pdf(String Address) {
// 驗證License
if (!getLicense()) {
return;
}
try {
long old = System.currentTimeMillis();
File file = new File("F:\\pdf/pdf3.pdf");// 輸出pdf路徑
Presentation pres = new Presentation(Address);//輸入pdf路徑
FileOutputStream fileOS = new FileOutputStream(file);
pres.save(fileOS, SaveFormat.Pdf);
fileOS.close();
long now = System.currentTimeMillis();
System.out.println("共耗時:" + ((now - old) / 1000.0) + "秒\n\n" + "文件保存在:" + file.getPath()); //轉化過程耗時
} catch (Exception e) {
e.printStackTrace();
}
}
Linux下編譯運行:
javac -cp /usr/local/temp/aspose-words-15.8.0-jdk16.jar Doc2Pdf.java
java -cp /usr/local/temp/aspose-words-15.8.0-jdk16.jar:/usr/local/temp Doc2Pdf
效果:
轉換文檔:
平均4.2s。
共耗時:4.213秒
共耗時:4.2秒
共耗時:4.361秒
共耗時:3.959秒
共耗時:4.235秒
轉換ppt:
平均15.5s
共耗時:15.979秒
共耗時:15.212秒
共耗時:14.663秒
轉換excel:
平均2.6s
共耗時:2.67秒
共耗時:2.524秒
共耗時:2.741秒
共耗時:2.7秒
暫時就發現這些實現Office轉PDF的方法,以後還有其他方法的話,歡迎大家評論共討,同時本博客也會繼續更新下去。