[更文挑战]iText番盘-PDF神器-7

180 阅读3分钟

「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战

PDF神器iText英文版翻译与学习

作者: 薛大郎.
英文原版:iText in Action 2nd Edition.pdf

坚持. 分享. 成长. 利他 !

一. 前言

愚公移山, 只为感动自己

前段时间网络上对于祖传代码或者屎山有了一个新桥段(屎山桥段), 我想对于大部分的开发来说都感同身受. 也有少数人会心中告诫自己, 鞭策自己, 不给愚公添麻烦. 那些意识到此问题, 并付诸行动, 还带动身边XDM一起向愚公学习的人, 众志成城, 奈何我本将心向明月,奈何明月照沟渠, 终究还是淹没在自己和别人的借口里. 那些还在帮助愚公的人, 我想也只是感动了自己, 后来者虽然也没有太多WTF, 但不一定有称赞, 埋没在@author里.

二.正文.

4.2 添加链接、图片、章、节

在iText中添加一个链接, 我们一般使用的是Anchor(描点), 它的使用很简单;

// 这是iText in Action中的例子. 
Paragraph country = new Paragraph();
// 链接可以只是个文案而已, 可以直接设置他的字体
Anchor dest = new Anchor(rs.getString("country"), FilmFonts.BOLD);
// 注意这里很关键, 通过设置其name属性, 可以完成文档内的导航定位;
dest.setName(rs.getString("country_id"));
country.add(dest);
country.add(String.format(": %d movies", rs.getInt("c")));
document.add(country);
for(Movie movie : PojoFactory.getMovies(
    connection, rs.getString("country_id"))) {
    imdb = new Anchor(movie.getMovieTitle());
    // 当然最主要的我们还是可以设置真正的 world链接.
    imdb.setReference(String.format("http://www.imdb.com/title/tt%s/", movie.getImdb()));
    document.add(imdb);
    document.add(Chunk.NEWLINE);
}
document.newPage();
...
Anchor toUS = new Anchor("Go to first page.");
// 通过使用setReference("#" + name);之前设置过的Anchor的name, 可以直接锚点过去.
toUS.setReference("#US");
document.add(toUS);

当然你以为这样就完了吗? 错了, iText还帮我们可以直接打开相对的某个文件

Chunk imdb = new Chunk("Internet Movie Database", FilmFonts.ITALIC);
// 可以直接通过Chunk来添加一个链接, 也关联到 "Internet Movie Database"
imdb.setAnchor(new URL("http://www.imdb.com/"));
p = new Paragraph("Click on a country, and you'll get a list of movies," + " containing links  to the ");
p.add(imdb);
p.add(".");
document.add(p);
p = new Paragraph("This list can be found in a ");
Chunk page1 = new Chunk("separate document");
// 通过setRemoteGoto方法可以 对应的文件中的某个页面, 具体我们可以看下后边的各个重载方法. 
page1.setRemoteGoto("movie_links_1.pdf", 1);

// 某个文件的对应设置了名字的 锚点
public Chunk setRemoteGoto(final String filename, final String name) {
   return setAttribute(REMOTEGOTO, new Object[] { filename, name });
}
// 某个文件的某页
public Chunk setRemoteGoto(final String filename, final int page) {
   return setAttribute(REMOTEGOTO, new Object[] { filename,
         Integer.valueOf(page) });
}
// 直接跳转到本文件的某个设置了**reference**的 锚点
public Chunk setLocalGoto(final String name) {
   return setAttribute(LOCALGOTO, name);
}
// 直接跳转到本文件的某个设置了**name**的 锚点
public Chunk setLocalDestination(final String name) {
   return setAttribute(LOCALDESTINATION, name);
}

这是个必要的需要学习的内容, 那就是给Pdf添加章节, 尤其是长文的pdf. iText也为我们做好了抽象和很好用的Api. iText是按照Section为Chapter的父类来设计的, 也非常好理解,Chapter确实就是特殊的Section. 对于我们日常开发来说, 可能更多的是没有相关的父子类设计的. 所以说java3大特性中的抽象永远都是目标. 直接上案例代码.


title = new Paragraph(EPOCH[epoch], FONT[0]);
// 这就是章节的类,  可以直接添加title 和章节数, 章节数可以自定义
// 当然我们也可以使用iText给我们提供的ChapterAutoNumber(Chapter的子类)添加章节. 
chapter = new Chapter(title, epoch + 1);
...
title = new Paragraph(String.format("The year %d", movie.getYear()), FONT[1]);
// 章下边就是节了.
section = chapter.addSection(title);
// 也可以设置标签标题
section.setBookmarkTitle(String.valueOf(movie.getYear()));
// 设置识别码
section.setIndentation(30);
// 设置标签是否开启. 默认
section.setBookmarkOpen(false);
section.setNumberStyle(
Section.NUMBERSTYLE_DOTTED_WITHOUT_FINAL_DOT);
section.add(...);
...
title = new Paragraph(movie.getMovieTitle(), FONT[2]);
subsection = section.addSection(title);
subsection.setIndentationLeft(20
subsection.setNumberDepth(1);
subsection.add(...);

**图片由于内容较多, 我们明天深入学习下. **