6.1 使用PdfReader读取PDF
检索文档和页面信息
D:/data/iText/inAction/chapter03/image_direct.pdf
Number of pages: 1
Size of page 1: [0.0,0.0,283.0,416.0]
Rotation of page 1: 0
Page size with rotation of page 1: Rectangle: 283.0x416.0 (rot: 0 degrees)
Is rebuilt? false
Is encrypted? false
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfReader;public class PageInformation {/** The resulting text file with info about a PDF. */public static final String RESULT= "D:/data/iText/inAction/chapter06/page_info.txt";/*** Main method.* @param args no arguments needed* @throws DocumentException * @throws IOException*/public static void main(String[] args)throws DocumentException, IOException {// Inspecting PDFsPrintWriter writer = new PrintWriter(new FileOutputStream(RESULT));inspect(writer, "D:/data/iText/inAction/chapter03/image_direct.pdf");writer.close();}/*** Inspect a PDF file and write the info to a txt file* @param writer Writer to a text file* @param filename Path to the PDF file* @throws IOException*/public static void inspect(PrintWriter writer, String filename)throws IOException {PdfReader reader = new PdfReader(filename);writer.println(filename);writer.print("Number of pages: ");writer.println(reader.getNumberOfPages());Rectangle mediabox = reader.getPageSize(1);writer.print("Size of page 1: [");writer.print(mediabox.getLeft());writer.print(',');writer.print(mediabox.getBottom());writer.print(',');writer.print(mediabox.getRight());writer.print(',');writer.print(mediabox.getTop());writer.println("]");writer.print("Rotation of page 1: ");writer.println(reader.getPageRotation(1));writer.print("Page size with rotation of page 1: ");writer.println(reader.getPageSizeWithRotation(1));writer.print("Is rebuilt? ");writer.println(reader.isRebuilt());writer.print("Is encrypted? ");writer.println(reader.isEncrypted());writer.println();writer.flush();}
}
Page Size 页面大小
损坏的PDF
加密的PDF
使用PdfReader降低内存
部分读取
/*** Do a full read of a PDF file* @param writer a writer to a report file* @param filename the file to read* @throws IOException*/public static void fullRead(PrintWriter writer, String filename)throws IOException {long before = getMemoryUse();PdfReader reader = new PdfReader(filename);reader.getNumberOfPages();writer.println(String.format("Memory used by full read: %d",getMemoryUse() - before));writer.flush();}/*** Do a partial read of a PDF file* @param writer a writer to a report file* @param filename the file to read* @throws IOException*/public static void partialRead(PrintWriter writer, String filename)throws IOException {long before = getMemoryUse();PdfReader reader = new PdfReader(new RandomAccessFileOrArray(filename), null);reader.getNumberOfPages();writer.println(String.format("Memory used by partial read: %d",getMemoryUse() - before));writer.flush();}
选择页面
PdfReader.selectPages("3");
PdfReader.selectPages("4-8");
执行selectPages()后,页数就变成选中的实际页数,要注意越界。
import java.io.FileOutputStream;
import java.io.IOException;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;public class SelectPages {/** A resulting PDF file. */public static final String RESULT1 = "results/part2/chapter06/timetable_stamper.pdf";/** A resulting PDF file. */public static final String RESULT2 = "results/part2/chapter06/timetable_copy.pdf"; /*** Main method.* @param args no arguments needed* @throws DocumentException * @throws IOException*/public static void main(String[] args) throws IOException, DocumentException {PdfReader reader = new PdfReader("D:/data/iText/inAction/chapter03/movie_posters.pdf");reader.selectPages("4-8");manipulateWithStamper(reader);manipulateWithCopy(reader);}/*** Creates a new PDF based on the one in the reader* @param reader a reader with a PDF file* @throws IOException* @throws DocumentException*/private static void manipulateWithStamper(PdfReader reader)throws IOException, DocumentException {PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(RESULT1));stamper.close();}/*** Creates a new PDF based on the one in the reader* @param reader a reader with a PDF file* @throws IOException* @throws DocumentException*/private static void manipulateWithCopy(PdfReader reader)throws IOException, DocumentException {int n = reader.getNumberOfPages();Document document = new Document();PdfCopy copy = new PdfCopy(document, new FileOutputStream(RESULT2));document.open();for (int i = 0; i < n;) {copy.addPage(copy.getImportedPage(reader, ++i));}document.close();}}
6.2 从PDF拷贝页面
导入页面
import java.io.FileOutputStream;
import java.io.IOException;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;public class ImportingPages1 {/** The resulting PDF file. */public static final String RESULT= "D:/data/iText/inAction/chapter06/time_table_imported1.pdf";/*** Main method.* @param args no arguments needed* @throws DocumentException * @throws IOException*/public static void main(String[] args)throws IOException, DocumentException {// step 1Document document = new Document();// step 2PdfWriter writer= PdfWriter.getInstance(document, new FileOutputStream(RESULT));// step 3document.open();// step 4PdfPTable table = new PdfPTable(2);PdfReader reader = new PdfReader("D:/data/iText/inAction/chapter03/movie_posters.pdf");int n = reader.getNumberOfPages();PdfImportedPage page;for (int i = 1; i <= n; i++) {page = writer.getImportedPage(reader, i);table.addCell(Image.getInstance(page));}document.add(table);// step 5document.close();}
}
缩放和叠加页面
叠加PDF页面
import java.io.FileOutputStream;
import java.io.IOException;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfGState;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;public class Layers {/** The resulting PDF. */public static final String SOURCE= "D:/data/iText/inAction/chapter06/layers_orig.pdf";/** The resulting PDF. */public static final String RESULT= "D:/data/iText/inAction/chapter06/layers.pdf";/** The movie poster. */public static final String RESOURCE= "E:/study/PDF/SourceCodeiText/itext-book/book/resources/img/loa.jpg";/*** Main method.* @param args no arguments needed* @throws DocumentException * @throws IOException*/public static void main(String[] args)throws IOException, DocumentException {new Layers().createPdf(SOURCE);// Create a readerPdfReader reader = new PdfReader(SOURCE);// step 1Document document = new Document(PageSize.A5.rotate());// step 2PdfWriter writer= PdfWriter.getInstance(document, new FileOutputStream(RESULT));// step 3document.open();// step 4PdfContentByte canvas = writer.getDirectContent();PdfImportedPage page;BaseFont bf= BaseFont.createFont(BaseFont.ZAPFDINGBATS, "", BaseFont.EMBEDDED);for (int i = 0; i < reader.getNumberOfPages(); ) {page = writer.getImportedPage(reader, ++i);canvas.addTemplate(page, 1f, 0, 0.4f, 0.4f, 72, 50 * i);canvas.beginText();canvas.setFontAndSize(bf, 20);canvas.showTextAligned(Element.ALIGN_CENTER,String.valueOf((char)(181 + i)), 496, 150 + 50 * i, 0);canvas.endText();}// step 5document.close();}/*** Creates a PDF document.* @param filename the path to the new PDF document* @throws DocumentException * @throws IOException*/public void createPdf(String filename)throws IOException, DocumentException {// step 1Document document = new Document(PageSize.POSTCARD, 30, 30, 30, 30);// step 2PdfWriter writer = PdfWriter.getInstance(document,new FileOutputStream(filename));// step 3document.open();// step 4PdfContentByte under = writer.getDirectContentUnder();// Page 1: a rectangledrawRectangle(under, PageSize.POSTCARD.getWidth(), PageSize.POSTCARD.getHeight());under.setRGBColorFill(0xFF, 0xD7, 0x00);under.rectangle(5, 5, PageSize.POSTCARD.getWidth() - 10, PageSize.POSTCARD.getHeight() - 10);under.fill();document.newPage();// Page 2: an imagedrawRectangle(under, PageSize.POSTCARD.getWidth(), PageSize.POSTCARD.getHeight());Image img = Image.getInstance(RESOURCE);img.setAbsolutePosition((PageSize.POSTCARD.getWidth() - img.getScaledWidth()) / 2,(PageSize.POSTCARD.getHeight() - img.getScaledHeight()) / 2);document.add(img);document.newPage();// Page 3: the words "Foobar Film Festival"drawRectangle(under, PageSize.POSTCARD.getWidth(), PageSize.POSTCARD.getHeight());;Paragraph p = new Paragraph("Foobar Film Festival", new Font(FontFamily.HELVETICA, 22));p.setAlignment(Element.ALIGN_CENTER);document.add(p);document.newPage();// Page 4: the words "SOLD OUT"drawRectangle(under, PageSize.POSTCARD.getWidth(), PageSize.POSTCARD.getHeight());PdfContentByte over = writer.getDirectContent();over.saveState();float sinus = (float)Math.sin(Math.PI / 60);float cosinus = (float)Math.cos(Math.PI / 60);BaseFont bf = BaseFont.createFont();over.beginText();over.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE);over.setLineWidth(1.5f);over.setRGBColorStroke(0xFF, 0x00, 0x00);over.setRGBColorFill(0xFF, 0xFF, 0xFF);over.setFontAndSize(bf, 36);over.setTextMatrix(cosinus, sinus, -sinus, cosinus, 50, 324);over.showText("SOLD OUT");over.setTextMatrix(0, 0);over.endText();over.restoreState();// step 5document.close();}/*** Draws a rectangle* @param content the direct content layer* @param width the width of the rectangle* @param height the height of the rectangle*/public static void drawRectangle(PdfContentByte content, float width, float height) {content.saveState();PdfGState state = new PdfGState();state.setFillOpacity(0.6f);content.setGState(state);content.setRGBColorFill(0xFF, 0xFF, 0xFF);content.setLineWidth(3);content.rectangle(0, 0, width, height);content.fillStroke();content.restoreState();}
}
导入公司信封
从第N页复制页面
6.3 使用PdfStamper添加内容
在绝对位置添加内容
PdfStamper.getOverContent() 类似 getDirectContent()
import java.io.FileOutputStream;
import java.io.IOException;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.ygsoft.abc.component.cdes.itext.chapter1.HelloWorldLandscape1;
import com.ygsoft.abc.component.cdes.itext.chapter1.HelloWorldLandscape2;public class StampText {/** A resulting PDF file. */public static final String RESULT1= "D:/data/iText/inAction/chapter06/hello1.pdf";/** A resulting PDF file. */public static final String RESULT2= "D:/data/iText/inAction/chapter06/hello2.pdf";/** A resulting PDF file. */public static final String RESULT3= "D:/data/iText/inAction/chapter06/hello3.pdf";/*** Main method.* @param args no arguments needed* @throws DocumentException * @throws IOException*/public static void main(String[] args)throws DocumentException, IOException {HelloWorldLandscape1.main(args);HelloWorldLandscape2.main(args);stamp(HelloWorldLandscape1.RESULT, RESULT1);stampIgnoreRotation(HelloWorldLandscape1.RESULT, RESULT2);stamp(HelloWorldLandscape2.RESULT, RESULT3);}/*** Manipulates a PDF file src with the file dest as result* @param src the original PDF* @param dest the resulting PDF* @throws IOException* @throws DocumentException*/public static void stamp(String src, String dest)throws IOException, DocumentException {PdfReader reader = new PdfReader(src);PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));PdfContentByte canvas = stamper.getOverContent(1);ColumnText.showTextAligned(canvas,Element.ALIGN_LEFT, new Phrase("Hello people!"), 36, 540, 0);stamper.close();}/*** Manipulates a PDF file src with the file dest as result* @param src the original PDF* @param dest the resulting PDF* @throws IOException* @throws DocumentException*/public static void stampIgnoreRotation(String src, String dest)throws IOException, DocumentException {PdfReader reader = new PdfReader(src);PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));stamper.setRotateContents(false);PdfContentByte canvas = stamper.getOverContent(1);ColumnText.showTextAligned(canvas,Element.ALIGN_LEFT, new Phrase("Hello people!"), 36, 540, 0);stamper.close();}
}
2步创建PDF
第一步,创建文档内容,第二步,添加页码
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;public class TwoPasses {/** The resulting PDF file. */public static final String RESULT= "results/part2/chapter06/page_x_of_y.pdf";/*** Main method.* @param args no arguments needed* @throws DocumentException * @throws IOException * @throws SQLException* @throws SQLException*/public static void main(String[] args)throws SQLException, DocumentException, IOException {// FIRST PASS, CREATE THE PDF WITHOUT HEADER// step 1Document document = new Document(PageSize.A4, 36, 36, 54, 36);// step 2ByteArrayOutputStream baos = new ByteArrayOutputStream();PdfWriter.getInstance(document, baos);// step 3document.open();// step 4// PDF文档创建...// step 5document.close();// SECOND PASS, ADD THE HEADER// Create a readerPdfReader reader = new PdfReader(baos.toByteArray());// Create a stamperPdfStamper stamper= new PdfStamper(reader, new FileOutputStream(RESULT));// Loop over the pages and add a header to each pageint n = reader.getNumberOfPages();for (int i = 1; i <= n; i++) {getHeaderTable(i, n).writeSelectedRows(0, -1, 34, 803, stamper.getOverContent(i));}// Close the stamperstamper.close();}/*** Create a header table with page X of Y* @param x the page number* @param y the total number of pages* @return a table that can be used as header*/public static PdfPTable getHeaderTable(int x, int y) {PdfPTable table = new PdfPTable(2);table.setTotalWidth(527);table.setLockedWidth(true);table.getDefaultCell().setFixedHeight(20);table.getDefaultCell().setBorder(Rectangle.BOTTOM);table.addCell("FOOBAR FILMFESTIVAL");table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);table.addCell(String.format("Page %d of %d", x, y));return table;}
}
添加公司信封到一个存在的文档
/*** Manipulates a PDF file src with the file dest as result* @param src the original PDF* @param stationery a PDF that will be added as background* @param dest the resulting PDF* @throws IOException* @throws DocumentException*/public void manipulatePdf(String src, String stationery, String dest)throws IOException, DocumentException {// Create readersPdfReader reader = new PdfReader(src);PdfReader s_reader = new PdfReader(stationery);// Create the stamperPdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));// Add the stationery to each pagePdfImportedPage page = stamper.getImportedPage(s_reader, 1);int n = reader.getNumberOfPages();PdfContentByte background;for (int i = 1; i <= n; i++) {background = stamper.getUnderContent(i);background.addTemplate(page, 0, 0);}// CLose the stamperstamper.close();}
插入页面到一个存在的文档
填充PDF表单
6.4 使用PdfCopy 拷贝页面
拼接和拆分PDF文档
拼接文档
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.SQLException;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;public class ConcatenateStamp {/** The resulting PDF file. */public static final String RESULT= "results/part2/chapter06/concatenated_stamped.pdf";/*** Main method.* @param args no arguments needed* @throws DocumentException * @throws IOException* @throws SQLException*/public static void main(String[] args)throws IOException, DocumentException, SQLException {// use old examples to create PDFsMovieLinks1.main(args);MovieHistory.main(args);// step 1Document document = new Document();// step 2PdfCopy copy = new PdfCopy(document, new FileOutputStream(RESULT));// step 3document.open();// step 4// reader for document 1PdfReader reader1 = new PdfReader(MovieLinks1.RESULT);int n1 = reader1.getNumberOfPages();// reader for document 2PdfReader reader2 = new PdfReader(MovieHistory.RESULT);int n2 = reader2.getNumberOfPages();// initializationsPdfImportedPage page;PdfCopy.PageStamp stamp;// Loop over the pages of document 1for (int i = 0; i < n1; ) {page = copy.getImportedPage(reader1, ++i);stamp = copy.createPageStamp(page);// add page numbersColumnText.showTextAligned(stamp.getUnderContent(), Element.ALIGN_CENTER,new Phrase(String.format("page %d of %d", i, n1 + n2)),297.5f, 28, 0);stamp.alterContents();copy.addPage(page);}// Loop over the pages of document 2for (int i = 0; i < n2; ) {page = copy.getImportedPage(reader2, ++i);stamp = copy.createPageStamp(page);// add page numbersColumnText.showTextAligned(stamp.getUnderContent(), Element.ALIGN_CENTER,new Phrase(String.format("page %d of %d", n1 + i, n1 + n2)),297.5f, 28, 0);stamp.alterContents();copy.addPage(page);}// step 5document.close();}
}
拆分文档
import java.io.FileOutputStream;
import java.io.IOException;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfReader;public class Burst {/** Format of the resulting PDF files. */public static final String RESULT= "D:/data/iText/inAction/chapter06/timetable_p%d.pdf";/*** Main method.* @param args no arguments needed* @throws DocumentException * @throws IOException*/public static void main(String[] args)throws IOException, DocumentException {// Create a readerPdfReader reader = new PdfReader("D:/data/iText/inAction/chapter03/movie_posters.pdf");// We'll create as many new PDFs as there are pagesDocument document;PdfCopy copy;// loop over all the pages in the original PDFint n = reader.getNumberOfPages();for (int i = 0; i < n; ) {// step 1document = new Document();// step 2copy = new PdfCopy(document,new FileOutputStream(String.format(RESULT, ++i)));// step 3document.open();// step 4copy.addPage(copy.getImportedPage(reader, i));// step 5document.close();}}}
PdfCopy VS PdfSmartCopy
PdfSmartCopy 继承自PdfCopy,其会检查每页添加的冗余对象, 因此可以节省大量磁盘空间或
带宽。这种额外的“智慧”是要付出代价的。PdfSmartCopy 需要更多的内存和时间去拼接文档。
文件大小、带宽优先,选PdfSmartCopy
内存、时间优先,选PdfCopy
拼接表单