java使用itext如何直接生成pdf
需求背景
在工作中經(jīng)常會(huì)有生成pdf文件的需求,大多數(shù)情況下,我們只需要使用pdf模版添加表單域,就足以勝任了。但是有一些特殊的需求,需要生成較為復(fù)雜的文件,如動(dòng)態(tài)數(shù)據(jù)表格、插入圖像等。
這時(shí)候,我們就可以使用拼接的方式,將pdf文件內(nèi)容一段段拼上去,組合成一個(gè)pdf文件,來靈活的操縱文件的排版與內(nèi)存形式。
itext 的使用
依賴
<dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.5.13</version> </dependency> <!-- https://mvnrepository.com/artifact/com.itextpdf/itext-asian --> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itext-asian</artifactId> <version>5.2.0</version> </dependency>
簡(jiǎn)單示例
生成一個(gè)內(nèi)容為“Hello World”的pdf文件
import com.itextpdf.text.*; import com.itextpdf.text.pdf.PdfWriter; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.util.logging.Level; import java.util.logging.Logger; /** * 生成一個(gè)內(nèi)容為“Hello World”的pdf文件 * @author ym */ public class HelloWorld { public static void main(String[] args) { String FILE_DIR = "./"; // 項(xiàng)目根目錄:盤符:/.../.../項(xiàng)目名稱,注意:點(diǎn)號(hào)并不表示當(dāng)前類文件所在的目錄,而是項(xiàng)目目錄下 //Step 1—Create a Document. Document document = new Document(); try { //Step 2—Get a PdfWriter instance. PdfWriter.getInstance(document, new FileOutputStream(FILE_DIR + "createSamplePDF.pdf")); //Step 3—Open the Document. document.open(); //Step 4—Add content. document.add(new Paragraph("Hello World")); //Step 5—Close the Document. document.close(); } catch (DocumentException ex) { Logger.getLogger(HelloWorld.class.getName()).log(Level.SEVERE, null, ex); } catch (FileNotFoundException ex) { Logger.getLogger(HelloWorld.class.getName()).log(Level.SEVERE, null, ex); } } }
基礎(chǔ)設(shè)置(頁(yè)面大小、邊距、字體等)
//頁(yè)面大小 Rectangle rect = new Rectangle(PageSize.A4.rotate()); //頁(yè)面背景色 rect.setBackgroundColor(BaseColor.ORANGE); // page , 外邊距 marginLeft marginRight marginTop marginBottom Document doc = new Document(rect,90, 90, 30, 40); // 新開一頁(yè) doc.newPage(); /** * 段落設(shè)置 */ Paragraph titleParagraph = new Paragraph("hello world!", getChineseTitleFont()); titleParagraph.setAlignment(Element.ALIGN_CENTER);// 居中 titleParagraph.setFirstLineIndent(24);// 首行縮進(jìn) titleParagraph.setLeading(35f);// 行間距 titleParagraph.setSpacingBefore(5f);// 設(shè)置上空白 titleParagraph.setSpacingAfter(10f);// 設(shè)置段落下空白 //支持中文 設(shè)置字體,字體顏色、大小等 public Font getChineseTitleFont() throws RuntimeException { Font ChineseFont = null; try { /** * name – the name of the font or its location on file * encoding – the encoding to be applied to this font * embedded – true if the font is to be embedded in the PDF */ BaseFont simpChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); ChineseFont = new Font(simpChinese, 15, Font.BOLD, BaseColor.BLACK); } catch (DocumentException e) { log.error("getChineseFont" ,"字體異常",e); throw new RuntimeException("getChineseFont字體異常",e); } catch (IOException e) { log.error("getChineseFont" ,"字體異常",e); throw new RuntimeException("getChineseFont字體異常",e); } return ChineseFont; }
段落內(nèi)部,特殊設(shè)置關(guān)鍵字 字體或顏色
// 文本內(nèi)容 String content = "This is a sample text with different colors."; String[] words = content.split(" "); // 將文本拆分為單詞 for (String word : words) { Chunk chunk = new Chunk(word); // 創(chuàng)建一個(gè)新的 Chunk // 如果單詞是 "different",則設(shè)置為紅色 if (word.equals("different")) { chunk.setForegroundColor(BaseColor.RED); } // 如果單詞是 "colors.",則設(shè)置為藍(lán)色 if (word.equals("colors.")) { chunk.setForegroundColor(BaseColor.BLUE); } contentParagraph.add(chunk); // 將 Chunk 添加到段落中 contentParagraph.add(" "); // 添加單詞之間的空格 } document.add(contentParagraph); // 將段落添加到文檔中
生成動(dòng)態(tài)表格
// 創(chuàng)建一個(gè)包含5列的表格 PdfPTable table = new PdfPTable(5); // 添加表頭 table.addCell("Header 1"); table.addCell("Header 2"); table.addCell("Header 3"); table.addCell("Header 4"); table.addCell("Header 5"); // 添加動(dòng)態(tài)數(shù)據(jù)到表格 for (int i = 0; i < 10; i++) { table.addCell("Data " + i + ", 1"); table.addCell("Data " + i + ", 2"); table.addCell("Data " + i + ", 3"); table.addCell("Data " + i + ", 4"); table.addCell("Data " + i + ", 5"); } document.add(table); /** * 如果需要更精細(xì)的控制屬性 */ cell = new PdfPCell(new Phrase("title1",fontChinese)); cell.setColspan(1);//設(shè)置所占列數(shù) cell.setRowspan(1);//合并行 cell.setHorizontalAlignment(Element.ALIGN_CENTER);//設(shè)置水平居中 cell.setVerticalAlignment(Element.ALIGN_MIDDLE);//設(shè)置垂直居中 cell.setFixedHeight(30);//設(shè)置高度 table.addCell(cell);
頁(yè)腳展示頁(yè)數(shù)
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(FILE_DIR + "createSamplePDF.pdf")); writer.setPageEvent(new FooterEvent()); public class FooterEvent extends PdfPageEventHelper { //總頁(yè)數(shù) PdfTemplate totalPage; //字體 Font font; { try { BaseFont chinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); font = new Font(chinese,10); } catch (DocumentException | IOException e) { e.printStackTrace(); } } //打開文檔時(shí),創(chuàng)建一個(gè)總頁(yè)數(shù)的模版 @Override public void onOpenDocument(PdfWriter writer, Document document) { PdfContentByte cb = writer.getDirectContent(); totalPage = cb.createTemplate(50, 9); } @Override public void onEndPage(PdfWriter writer, Document document) { //創(chuàng)建一個(gè)兩列的表格 PdfPTable table = new PdfPTable(2); try { table.setTotalWidth(PageSize.A4.getWidth());//總寬度為A4紙張寬度 table.setLockedWidth(true);//鎖定列寬 table.setWidths(new int[]{50, 50});//設(shè)置每列寬度 PdfPCell cell = new PdfPCell(new Phrase("第"+document.getPageNumber() + " 頁(yè),共", font)); cell.setHorizontalAlignment(Element.ALIGN_RIGHT);//設(shè)置水平右對(duì)齊 cell.setVerticalAlignment(Element.ALIGN_MIDDLE);//設(shè)置垂直居中 cell.disableBorderSide(15);//隱藏全部邊框 table.addCell(cell); PdfPCell cell1 = new PdfPCell(Image.getInstance(totalPage));//共 頁(yè) cell1.setHorizontalAlignment(Element.ALIGN_LEFT);//設(shè)置水平左對(duì)齊 cell1.setVerticalAlignment(Element.ALIGN_MIDDLE);//設(shè)置垂直居中 cell1.disableBorderSide(15);//隱藏全部邊框 table.addCell(cell1); table.writeSelectedRows(0, -1, 0, 30, writer.getDirectContent()); } catch (Exception e) { throw new ExceptionConverter(e); } } @Override public void onCloseDocument(PdfWriter writer, Document document) { String text = "" +String.valueOf(writer.getPageNumber()) +"頁(yè)"; ColumnText.showTextAligned(totalPage, Element.ALIGN_MIDDLE, new Paragraph(text, font), 0, 0, 0); } }
其他
設(shè)置密碼
PdfWriter writer = PdfWriter.getInstance(doc, out); // 設(shè)置密碼為:"World" writer.setEncryption("Hello".getBytes(), "World".getBytes(), PdfWriter.ALLOW_SCREENREADERS, PdfWriter.STANDARD_ENCRYPTION_128); doc.open(); doc.add(new Paragraph("Hello World"));
添加水?。ū尘皥D)
//圖片水印 PdfReader reader = new PdfReader(FILE_DIR + "setWatermark.pdf"); PdfStamper stamp = new PdfStamper(reader, new FileOutputStream(FILE_DIR + "setWatermark2.pdf")); Image img = Image.getInstance("resource/watermark.jpg"); img.setAbsolutePosition(200, 400); PdfContentByte under = stamp.getUnderContent(1); under.addImage(img); //文字水印 PdfContentByte over = stamp.getOverContent(2); over.beginText(); BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED); over.setFontAndSize(bf, 18); over.setTextMatrix(30, 30); over.showTextAligned(Element.ALIGN_LEFT, "DUPLICATE", 230, 430, 45); over.endText(); //背景圖 Image img2 = Image.getInstance("resource/test.jpg"); img2.setAbsolutePosition(0, 0); PdfContentByte under2 = stamp.getUnderContent(3); under2.addImage(img2); stamp.close(); reader.close();
目錄
// Code 1 document.add(new Chunk("Chapter 1").setLocalDestination("1")); document.newPage(); document.add(new Chunk("Chapter 2").setLocalDestination("2")); document.add(new Paragraph(new Chunk("Sub 2.1").setLocalDestination("2.1"))); document.add(new Paragraph(new Chunk("Sub 2.2").setLocalDestination("2.2"))); document.newPage(); document.add(new Chunk("Chapter 3").setLocalDestination("3")); // Code 2 PdfContentByte cb = writer.getDirectContent(); PdfOutline root = cb.getRootOutline(); // Code 3 @SuppressWarnings("unused") PdfOutline oline1 = new PdfOutline(root, PdfAction.gotoLocalPage("1", false), "Chapter 1"); PdfOutline oline2 = new PdfOutline(root, PdfAction.gotoLocalPage("2", false), "Chapter 2"); oline2.setOpen(false); @SuppressWarnings("unused") PdfOutline oline2_1 = new PdfOutline(oline2, PdfAction.gotoLocalPage("2.1", false), "Sub 2.1"); @SuppressWarnings("unused") PdfOutline oline2_2 = new PdfOutline(oline2, PdfAction.gotoLocalPage("2.2", false), "Sub 2.2"); @SuppressWarnings("unused") PdfOutline oline3 = new PdfOutline(root, PdfAction.gotoLocalPage("3", false), "Chapter 3");
Header, Footer
PdfWriter writer = PdfWriter.getInstance(doc, new FileOutputStream(FILE_DIR + "setHeaderFooter.pdf")); writer.setPageEvent(new PdfPageEventHelper() { public void onEndPage(PdfWriter writer, Document document) { PdfContentByte cb = writer.getDirectContent(); cb.saveState(); cb.beginText(); BaseFont bf = null; try { bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED); } catch (Exception e) { e.printStackTrace(); } cb.setFontAndSize(bf, 10); //Header float x = document.top(-20); //左 cb.showTextAligned(PdfContentByte.ALIGN_LEFT, "H-Left", document.left(), x, 0); //中 cb.showTextAligned(PdfContentByte.ALIGN_CENTER, writer.getPageNumber()+ " page", (document.right() + document.left())/2, x, 0); //右 cb.showTextAligned(PdfContentByte.ALIGN_RIGHT, "H-Right", document.right(), x, 0); //Footer float y = document.bottom(-20); //左 cb.showTextAligned(PdfContentByte.ALIGN_LEFT, "F-Left", document.left(), y, 0); //中 cb.showTextAligned(PdfContentByte.ALIGN_CENTER, writer.getPageNumber()+" page", (document.right() + document.left())/2, y, 0); //右 cb.showTextAligned(PdfContentByte.ALIGN_RIGHT, "F-Right", document.right(), y, 0); cb.endText(); cb.restoreState(); } }); doc.open(); doc.add(new Paragraph("1 page")); doc.newPage(); doc.add(new Paragraph("2 page")); doc.newPage(); doc.add(new Paragraph("3 page")); doc.newPage(); doc.add(new Paragraph("4 page"));
分割 PDF
FileOutputStream out = new FileOutputStream(FILE_DIR + "splitPDF.pdf"); Document document = new Document(); PdfWriter.getInstance(document, out); document.open(); document.add(new Paragraph("1 page")); document.newPage(); document.add(new Paragraph("2 page")); document.newPage(); document.add(new Paragraph("3 page")); document.newPage(); document.add(new Paragraph("4 page")); document.close(); PdfReader reader = new PdfReader(FILE_DIR + "splitPDF.pdf"); Document dd = new Document(); PdfWriter writer = PdfWriter.getInstance(dd, new FileOutputStream(FILE_DIR + "splitPDF1.pdf")); dd.open(); PdfContentByte cb = writer.getDirectContent(); dd.newPage(); cb.addTemplate(writer.getImportedPage(reader, 1), 0, 0); dd.newPage(); cb.addTemplate(writer.getImportedPage(reader, 2), 0, 0); dd.close(); writer.close(); Document dd2 = new Document(); PdfWriter writer2 = PdfWriter.getInstance(dd2, new FileOutputStream(FILE_DIR + "splitPDF2.pdf")); dd2.open(); PdfContentByte cb2 = writer2.getDirectContent(); dd2.newPage(); cb2.addTemplate(writer2.getImportedPage(reader, 3), 0, 0); dd2.newPage(); cb2.addTemplate(writer2.getImportedPage(reader, 4), 0, 0); dd2.close(); writer2.close();
合并 PDF
PdfReader reader1 = new PdfReader(FILE_DIR + "splitPDF1.pdf"); PdfReader reader2 = new PdfReader(FILE_DIR + "splitPDF2.pdf"); FileOutputStream out = new FileOutputStream(FILE_DIR + "mergePDF.pdf"); Document document = new Document(); PdfWriter writer = PdfWriter.getInstance(document, out); document.open(); PdfContentByte cb = writer.getDirectContent(); int totalPages = 0; totalPages += reader1.getNumberOfPages(); totalPages += reader2.getNumberOfPages(); java.util.List<PdfReader> readers = new ArrayList<PdfReader>(); readers.add(reader1); readers.add(reader2); int pageOfCurrentReaderPDF = 0; Iterator<PdfReader> iteratorPDFReader = readers.iterator(); // Loop through the PDF files and add to the output. while (iteratorPDFReader.hasNext()) { PdfReader pdfReader = iteratorPDFReader.next(); // Create a new page in the target for each source page. while (pageOfCurrentReaderPDF < pdfReader.getNumberOfPages()) { document.newPage(); pageOfCurrentReaderPDF++; PdfImportedPage page = writer.getImportedPage(pdfReader, pageOfCurrentReaderPDF); cb.addTemplate(page, 0, 0); } pageOfCurrentReaderPDF = 0; } out.flush(); document.close(); out.close();
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Springboot如何實(shí)現(xiàn)Web系統(tǒng)License授權(quán)認(rèn)證
這篇文章主要介紹了Springboot如何實(shí)現(xiàn)Web系統(tǒng)License授權(quán)認(rèn)證,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05聊聊spring boot的WebFluxTagsProvider的使用
這篇文章主要介紹了聊聊spring boot的WebFluxTagsProvider的使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07springsecurity第三方授權(quán)認(rèn)證的項(xiàng)目實(shí)踐
Spring security 是一個(gè)強(qiáng)大的和高度可定制的身份驗(yàn)證和訪問控制框架,本文主要介紹了springsecurity第三方授權(quán)認(rèn)證的項(xiàng)目實(shí)踐,具有一定的參考價(jià)值,感興趣可以了解一下2023-08-08Java中Stream實(shí)現(xiàn)List排序的六個(gè)核心技巧總結(jié)
這篇文章主要介紹了Java中Stream實(shí)現(xiàn)List排序的六個(gè)核心技巧,分別是自然序排序、反向排序、空值安全處理、多字段組合排序、并行流加速、原地排序等,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-04-04