一.介绍

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(); }

五.源码

https://github.com/zwxbest/Demo/tree/master/itextDemo

使用iText快速更新书签的更多相关文章

  1. 如何快速更新长缓存的 HTTP 资源

    前言 HTTP 缓存时间一直让开发者头疼.时间太短,性能不够好:时间太长,更新不及时.当遇到严重问题需紧急修复时,尽管后端文件可快速替换,但前端文件仍从本地缓存加载,导致更新长时间无法生效. 对于这个 ...

  2. 论文写作中快速更新Word里面交叉引用的编号,巧用MathType

    点击插入编号>>更新,即可快速更新交叉引用的编号,不用一个一个更新域!

  3. WPF界面开发必备技能!TreeListView - 如何快速更新多个项目属性

    DevExpress广泛应用于ECM企业内容管理. 成本管控.进程监督.生产调度,在企业/政务信息化管理中占据一席重要之地.通过DevExpress WPF Controls,您能创建有着强大互动功能 ...

  4. 利用ROWID 快速更新单表记录

    -----对于普通表 实现: UPDATE T_PM_DEPOSIT_HIS b SET flag = SUBSTR( flag, 1, 8 )||'4'|| CASE WHEN term <= ...

  5. 以A表中的值快速更新B表中记录的方法

    1.问题描述 有两张表,A表记录了某些实体的新属性,B表记录了每个实体的旧属性,现在打算用A中的属性值去更新B中相同实体的旧属性,如下图所示: 类似这样的需求,怎样做比较高效呢? 2.制作模拟数据   ...

  6. winform 数据(双向)绑定 快速更新实体

    写点东西感觉特别累,也已经很久没写了. 最近在做一个winform类型的系统,其涉及到大量的表,有些表又包含大量的字段,所以当添加.更新实体时便会十分的繁琐,一方面:需要把界面上的字段绑定到对应的实体 ...

  7. 【Azure API 管理】API Management如何有效且快速更新呢?如对APIs/Policy等设置内容

    问题描述 APIM中的内容(API, Policy)等内容,如果有需要更新时候,通常可以在Azure APIM门户上操作,通过一个接口一个设置的修改,也可以针对一个接口导入/导出的方式修改.当APIM ...

  8. android SDK 快速更新配置(转)

    http://blog.csdn.net/yy1300326388/article/details/45074447 1.强制使用http替换https链接 Tools>选择Options,勾选 ...

  9. android sdk国内快速更新下载

    Android SDK在线更新镜像服务器 http://www.androiddevtools.cn/ 目前正在使用的是:包含详细的配图流程 http://android-mirror.bugly.q ...

随机推荐

  1. 【AI】微软人工智能学习笔记(二)

    微软Azure机器学习服务 01|机器学习概述 首先上一张图, 这个图里面的大神是谁我也不清楚反正,但是看起来这句话说得很有哲理就贴出来了. 所以在人工智能领域下面的这个机器学习,到底是一个什么样的概 ...

  2. Codeforces-Anastasia and pebbles

    这是一道很有意思的(水)题. 地址戳:http://codeforces.com/problemset/problem/789/A 题目的大意呢,就是一个可爱的大姐姐的故事.说是啊,她每天都带着两个一 ...

  3. 【Java】【事件处理机制】

    import javax.swing.*;import java.awt.*;import java.awt.event.ActionEvent;import java.awt.event.Actio ...

  4. node.js中的http.response.end方法使用说明

    转载自:http://m.jb51.net/article/58468.htm 本文介绍了http.response.end的方法说明.语法.接收参数.使用实例和实现源码,需要的朋友可以参考下 方法说 ...

  5. Python3入门 Python3+Selenium做UI页面测试的学习

    https://ke.qq.com/course/310732 一直计划着系统地看看Python3,这两天不用加班了,在网上下了些资源,自己演练一番. Python3标识符保留字,直接命令行中可以查看 ...

  6. JavaSE习题 第六章 字符串和正则表达式

    Make efforts eveyday 问答题 1.对于字符串 String s1=new String("ok"); String s2=new String("ok ...

  7. linux JAVA_HOME和 java -version不匹配

    ~/.bashrc 中更新了jdk, JAVA_HOME 起效果了,但是java -version还是老的. 原因是/usr/bin/java   和usr/bin/javac是一个链接,得改. 使用 ...

  8. L1-047. 装睡

    水题直接上代码: #include<iostream> #include<algorithm> using namespace std; int main() { int n; ...

  9. 全排列问题Ⅱ(Java实现)

    题目: 给定一个可包含重复数字的序列,返回所有不重复的全排列. 示例: 输入: [1,1,2] 输出: [ [1,1,2], [1,2,1], [2,1,1] ]这个问题和我的上一篇问题分析的手法一样 ...

  10. 浅谈Java简单实现的生产者与消费者问题

    一.面对生产者和消费者的问题,首先我们得明白几点: 生产者:生产数据:消费者:消费数据.消费者在没有数据可供消费的情况下,不能消费:生产者在原数据没有被消费掉的情况下,不能生产新数据.假设,数据空间只 ...