package com.ifnoelse.pdf; import com.itextpdf.text.pdf.PdfReader; import com.itextpdf.text.pdf.PdfStamper; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; /** * Created by ifnoelse on 2017/2/25 0025. */ public class PDFUtil { private static Pattern bookmarkPattern = Pattern.compile("^[\t\\s ]*?([0-9.]+)?(.*?)/?[\t\\s ]*([0-9]+)[\t\\s ]*?$"); private static String blankRegex = "[\t\\s ]+"; public static String replaceBlank(String str) { return str.replaceAll(blankRegex, " ").trim(); } public static void addBookmark(String bookmarks, String srcFile, String destFile, int pageIndexOffset) { if (bookmarks != null && !bookmarks.isEmpty()) { if (bookmarks.trim().startsWith("http")) { addBookmark(PDFContents.getContentsByUrl(bookmarks), srcFile, destFile, pageIndexOffset); } else { addBookmark(Arrays.asList(bookmarks.split("\n")), srcFile, destFile, pageIndexOffset); } } } public static List<Bookmark> generateBookmark(String bookmarks, int pageIndexOffset, int minLens, int maxLnes) { return generateBookmark(Arrays.asList(bookmarks.split("\n")), pageIndexOffset, minLens, maxLnes); } public static List<Bookmark> generateBookmark(String bookmarks, int pageIndexOffset) { return generateBookmark(Arrays.asList(bookmarks.split("\n")), pageIndexOffset, Integer.MIN_VALUE, Integer.MAX_VALUE); } /** * Add a directory to the pdf file * * @param bookmarks Directory content, each list element is a directory content, such as:“1.1 Functional vs. Imperative Data Structures 1” * @param pageIndexOffset The pdf file is really the offset between the page number and the directory page number. * @param minLens Legal directory entry minimum length * @param maxLnes Legal directory entry maximum length * @return Returns a list of bookmarked content */ public static List<Bookmark> generateBookmark(List<String> bookmarks, int pageIndexOffset, int minLens, int maxLnes) { List<Bookmark> bookmarkList = new ArrayList<>(); for (String ln : bookmarks) { ln = replaceBlank(ln); if (ln.length() < minLens || ln.length() > maxLnes) continue; Matcher matcher = bookmarkPattern.matcher(ln); if (matcher.find()) { String seq = matcher.group(1); String title = replaceBlank(matcher.group(2)); int pageIndex = Integer.parseInt(matcher.group(3)); if (seq != null && bookmarkList.size() > 0) { Bookmark pre = bookmarkList.get(bookmarkList.size() - 1); if (pre.getSeq() == null || seq.startsWith(pre.getSeq())) { pre.addSubBookMarkBySeq(new Bookmark(seq, title, pageIndex + pageIndexOffset)); } else { bookmarkList.add(new Bookmark(seq, title, pageIndex + pageIndexOffset)); } } else { bookmarkList.add(new Bookmark(seq, title, pageIndex + pageIndexOffset)); } } else { bookmarkList.add(new Bookmark(replaceBlank(ln))); } } return bookmarkList; } public static void addBookmark(List<String> bookmarks, String srcFile, String destFile, int pageIndexOffset, int minLens, int maxLnes) { addBookmark(generateBookmark(bookmarks, pageIndexOffset, minLens, maxLnes), srcFile, destFile); } public static void addBookmark(List<String> bookmarks, String srcFile, String destFile, int pageIndexOffset) { addBookmark(bookmarks, srcFile, destFile, pageIndexOffset, Integer.MIN_VALUE, Integer.MAX_VALUE); } public static void addBookmark(Bookmark bookmark, String srcFile, String destFile) { addOutlines(Arrays.asList(bookmark.outlines()), srcFile, destFile); } public static void addBookmark(List<Bookmark> bookmarks, String srcFile, String destFile) { addOutlines(bookmarks.stream().map(Bookmark::outlines).collect(Collectors.toList()), srcFile, destFile); } private static void addOutlines(List<HashMap<String, Object>> outlines, String srcFile, String destFile) { try { class MyPdfReader extends PdfReader { public MyPdfReader(String fileName) throws IOException { super(fileName); unethicalreading = true; encrypted = false; } } PdfReader reader = new MyPdfReader(srcFile); PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(destFile)); stamper.setOutlines(outlines); stamper.close(); } catch (Exception e) { throw new RuntimeException(e); } } }