1. 程式人生 > >linux、windows word轉成pdf 來獲取總頁數 + POI修改word內容

linux、windows word轉成pdf 來獲取總頁數 + POI修改word內容

背景

因為本來用的是POI,調研了一些POI的api,雖然有一些獲取總頁數的方法,但是一旦word裡有圖片獲得的總頁數就不準確了。
看有大牛提到過用轉pdf的方法來獲取word總頁數,但是隻適用於windows平臺下,但我們甲方的伺服器是Linux的,所以才採用了另一款轉pdf的工具–Libreoffice

解決方法

String lowerFilePath = filePath.toLowerCase();
if (lowerFilePath.endsWith(".docx")) {
            XWPFDocument docx = new XWPFDocument(POIXMLDocument.openPackage
(lowerFilePath)); return docx.getProperties().getExtendedProperties().getUnderlyingProperties().getPages(); } else if (lowerFilePath.endsWith(".doc")) { HWPFDocument wordDoc = new HWPFDocument(new FileInputStream(lowerFilePath)); return wordDoc.getSummaryInformation
().getPageCount(); }

2.對於有圖片的word,可以先把它轉換成pdf,
3.然後再讀取pdf的頁數

侷限性

不得不說,利用這個工具將word轉化成pdf後,pdf中換行符的高度要比word中的換行符的高度要高。也就是說,如果word中的有一個換行符在一頁的最後面,那麼很有可能在pdf中這個換行符就要移到了下一頁去。
這就導致了會多出空白頁。
我目前是讓文件裡不要有太多的換行符,感覺我也不知道該怎麼做了

準備工作

需要先安裝Libreoffice這個軟體,因為利用它,可以用java程式碼來控制word轉pdf,且格式良好
1.安裝libreoffice(linux還需要裝unoconv),windows到官網下載安裝包,linux直接用命令列裝即可:

https://zh-cn.libreoffice.org/get-help/install-howto/linux/(linux版及libreoffice中文官網)
linux下:
(1)sudo apt install libreoffice
(2)linux還需要安裝unoconv)

2.測試安裝成功沒有:黑視窗直接敲命令,windows下:soffice –convert-to pdf example.docx
linux下: doc2pdf example.docx, windows需要新增path系統變數(C:\Program Files\LibreOffice 5\program),不然無法識別soffice命令

程式碼



import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.time.Duration;
import java.time.Instant;

import org.apache.commons.io.IOUtils;

import com.itextpdf.text.pdf.PdfReader;
/**
 * @author qjp
 *
 */
public class WordPdfUtils {
    //測試用
    public static void main(String[] args) {
        WordPdfUtils.getTotalPageByToPdf("E:/test.docx");
    }

    //word轉換成pdf,生成的pdf會放在同一目錄下
    //可以通過修改變數command,更改pdf生成的路徑
    public boolean wordConverterToPdf(String docxPath) throws IOException {
        File file = new File(docxPath);
        String path = file.getParent();
        Instant inst1 = Instant.now();
        try {
            String osName = System.getProperty("os.name");
            String command = "";
            if (osName.contains("Windows")) {
                //soffice --convert-to pdf  -outdir E:/nctcFile/報告   E:/nctcFile/報告/20171107_報告_IC卡讀寫機_2018.4.23_19時59分.docx
                command = "soffice --convert-to pdf  -outdir " + path + " " + docxPath;
            } else {
                command = "doc2pdf --output=" + path + File.separator + file.getName().replaceAll(".(?i)docx", ".pdf") + " " + docxPath;
            }
            String result = WordPdfUtils.executeCommand(command);
            System.out.println("生成pdf的result==" + result);
            if (result.equals("") || result.contains("writer_pdf_Export")) {
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
            try {
                throw e;
            } catch (Exception e1) {
                // TODO 自動生成的 catch 塊
                e1.printStackTrace();
            }
        }
        Instant inst2 = Instant.now();
        System.out.println("生成pdf耗費時間: " + Duration.between(inst1, inst2).getSeconds() + "秒");
        return false;
    }

    /*
     * 獲取pdf總頁數
     */
    public static int getPdfPage(String filepath){  
        int pagecount = 0;    
        PdfReader reader;  
        try {  
            reader = new PdfReader(filepath);  
            pagecount= reader.getNumberOfPages();   
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
        System.out.println("pdf的總頁數為:" + pagecount);  
        return pagecount;  
    }

    /*
     * 把word轉換成pdf,並獲取總頁數
     */
    public static int getTotalPageByToPdf(String sourceFile) {
        try {
            new WordPdfUtils().wordConverterToPdf(sourceFile);
            sourceFile = sourceFile.replace(".docx", ".pdf");//pdf是同名不同字尾
            int totalPage = WordPdfUtils.getPdfPage(sourceFile);
            return totalPage;
        } catch (IOException e) {
            // TODO 自動生成的 catch 塊
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * linux或windows命令執行
     */
    public static String executeCommand(String command) {
        StringBuffer output = new StringBuffer();
        Process p;
        InputStreamReader inputStreamReader = null;
        BufferedReader reader = null;
        try {
            p = Runtime.getRuntime().exec(command);
            p.waitFor();
            inputStreamReader = new InputStreamReader(p.getInputStream(), "UTF-8");
            reader = new BufferedReader(inputStreamReader);
            String line = "";
            while ((line = reader.readLine()) != null) {
                output.append(line + "\n");
            }
//            p.destroy();//程式會自己銷燬
        } catch (IOException e) {
            e.printStackTrace();
            return "執行生成pdf的命令列IOException時出錯";
        } catch (InterruptedException e) {
            e.printStackTrace();
            return "執行生成pdf的命令列時InterruptedException出錯";
        } finally {
            IOUtils.closeQuietly(reader);
            IOUtils.closeQuietly(inputStreamReader);
        }
        System.out.println(output.toString());
        return output.toString();

    }
}

這樣,最後就能獲取word的總頁數了,如果程式出了bug,歡迎給我留言~