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直接用命令列裝即可:
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,歡迎給我留言~