PDF技術(一)-Java實現Office系列文件轉PDF文件

最近,公司要求做個文件轉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進行轉換)

優點:

不需要安裝軟件、跨平臺

缺點:

  1. 失真問題比較大。(格式兼容差)
  2. 涉及到中文編碼問題。
  3. 效率比較低

具體實現

    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的方法,以後還有其他方法的話,歡迎大家評論共討,同時本博客也會繼續更新下去。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章