一.介紹
pdfbox基於Apache協議,商用無需開放源代碼。
iText基於APGL協議,打包和修改需發布源碼,除非花錢買斷。
二.用途
下載的電子書,有的書簽是FitHeight,也就是縮放后整個高度都顯示出來,頁面很小了。
我需要改成繼承,也就是XYZ,x是left,y是height,z是zoom,繼承的意思是根據當前pdf的縮放比例。
而且有的pdf書沒有目錄,大部分都是掃描版,需要目錄找資料,這年代北漂南漂基本一年一般家,那么多書來回累死。
目錄的話自己加太麻煩,從京東,亞馬迅,當當上找目錄,自動生成帶跳轉的目錄。
三.pdfBox
結論:有Bug,或者是我不會用。
public static void main(String[] args) throws Exception { String filename="E:\\PDF\\Go\\Go語言編程.pdf"; Catalog catalog=new Catalog(); catalog.OpenPdf(filename); catalog.AdjustCatalog(); }
//set scale to inherit public void AdjustCatalog() throws Exception { //獲取PDDocumentCatalog文檔目錄對象 PDDocumentCatalog catalog=document.getDocumentCatalog(); //獲取PDDocumentOutline文檔綱要對象 PDDocumentOutline outline=catalog.getDocumentOutline(); for (PDOutlineItem item:outline.children()) { System.out.println(item.getTitle()+item.getDestination()); AdjustCatalogRecurse(item); } } public void AdjustCatalogRecurse(PDOutlineItem item) throws Exception { // PDPageXYZDestination xyzDestination=new PDPageXYZDestination(); System.out.println(item.getDestination()==null?"null":item.getDestination().getClass()); System.out.println(item.getTitle()); // UpdatePageDestination(item.getDestination(),xyzDestination); // item.setDestination(xyzDestination); for (PDOutlineItem item_child:item.children()) { AdjustCatalogRecurse(item_child); } }
System.out.println(item.getDestination()==null?"null":item.getDestination().getClass());
getDestination()是獲取書簽的頁碼,縮放,頁面位置等信息,但是我測試了幾本,有的好用,有的全部是null,有的一半是null,真暈了。
左邊是用Xchange viewer打開,跳轉都沒問題,右邊是輸出的內容,全都是null
四.iText
結論:真難用,更新操作別扭。
PdfWriter只能新建用,更新的時候有保存書簽的PdfOutline不給用,只能用一堆
https://stackoverflow.com/questions/46716567/get-the-page-number-from-document-outline-bookmarks
一個pdfWriter只能寫不能讀,還要加一個reader拷貝到writer,和我理解的輸入輸出有點不一樣。
1.更新操作
有些pdf的書簽設置縮放等級是適應高度,每次看完幾頁一點書簽又變成小圖了。
下面是更新操作,我把其他全部的縮放等級都改成XYZ,xyz是繼承的,書簽的縮放等級和你當前頁面的一樣,你的頁面改成多大就多大,
其他的不動。
public void editBookmarks(String src, String dest) throws DocumentException, IOException { PdfReader reader = new PdfReader(src); PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest)); List<HashMap<String, Object>> list = SimpleBookmark.getBookmark(reader); changeList(list); stamper.setOutlines(list); stamper.close(); reader.close(); } public void changeList(List<HashMap<String, Object>> list) { for (HashMap<String, Object> entry : list) { for (String key : entry.keySet()) { if ("Kids".equals(key)) { Object o = entry.get(key); changeList((List<HashMap<String, Object>>) o); } else if ("Page".equals(key)) { String dest = (String) entry.get(key); entry.put("Page", dest.replaceAll("\\b(Fit|FitV|FITB|FITBH|FITBV|FITH|FITR)\\b", "XYZ")); } } } }
二.添加書簽
三點說明
1.目錄的頁碼是書上寫的頁碼,pdf中頁碼是實際的頁碼,包括目錄和前言,所以針對每個pdf都需要自己調整偏移
2.父目錄處理目前沒有考慮中文的情況,比如第一章,第十六章,過段時間抽空加上。
3.目錄上可能多個書簽同一頁,電腦因為縮放問題,會有點擠,如果強迫症就自己調吧,比如下面的21.4書簽,21.4.3亮了,因為他們是同一頁。
下面是spring攻略的pdf,測試過已經加好書簽了,太詳細的話做不到也沒時間。
public void createBookmarks(List<BookMark> booksmarks, String src, String dest) throws Exception { Document document = new Document(); reader=new PdfReader(src); PdfCopy copy = new PdfCopy(document, new FileOutputStream(dest)); document.open(); PdfOutline root = copy.getRootOutline(); copy.addDocument(reader); PdfDestination destination = new PdfDestination( PdfDestination.XYZ, -1, -1, 0); PdfAction action; copy.freeReader(reader); for(BookMark bookMark :booksmarks) { action = PdfAction.gotoLocalPage(bookMark.getNum(), destination, copy); new PdfOutline(root, action, bookMark.getTitle(), false); } copy.flush(); copy.close(); document.close(); }