SpringBoot实战(十六)集成iText

2024-02-24 06:50

本文主要是介绍SpringBoot实战(十六)集成iText,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

    • 1.简介
    • 2.Maven依赖
    • 3.实现示例:第1章
      • 1)创建PDF文件,写入 Hello World
      • 2)创建PDF,定制字体并写入多行(Rick Astley 歌词)
      • 3)创建PDF,定制字体并写入文字和图片(快棕狐)
      • 4)创建PDF,定制字体并根据csv文件写入表格(美国城市信息)
    • 4.实现示例:第2章
      • 1)创建PDF,画坐标轴
      • 2)创建PDF,画网格线
      • 3)创建PDF,写星球大战
      • 4)创建PDF,写星球大战(滚动版)
    • 5.实现示例:第3章
      • 1)创建PDF,简单的列渲染示例(纽约时代周刊)
      • 2)创建PDF,简单的表渲染示例(英格兰足球超级联赛)
      • 3)创建PDF,简单的事件渲染示例(UFO文件)
    • 6.实现示例:第4章
      • 1)创建PDF,添加文本批注
      • 2)创建PDF,添加链接批注
      • 3)创建PDF,添加线批注
      • 4)创建PDF,添加文本标记批注
      • 5)创建PDF,添加简单组件的批注(职位申请表)
      • 6)创建PDF,添加并填充表单(职位申请表)
      • 7)指定PDF,简单填充表单(职位申请表)
    • 7.实现示例:第5章
      • 1)创建PDF,添加可回复型批注
      • 2)根据PDF,填写并修改表单
      • 3)根据PDF,填充内容(页眉、页脚线、页脚页码、水印)
      • 4)根据PDF,改变页面(大小、边框、旋转)
    • 8.实现示例:第6章
      • 1)根据PDF,缩放尺寸(金门大桥)
      • 2)根据PDF,一分为四(金门大桥)
      • 3)根据PDF,多页合并(金门大桥)
      • 4)根据PDF,进行拼接(第88届奥斯卡)
      • 5)根据PDF,抽取指定页数进行拼接(第88届奥斯卡)
      • 6)根据PDF,拼接并添加目录(第88届奥斯卡)
      • 7)根据PDF,合并表格
      • 8)根据PDF,批量填写并合并表格
      • 9)根据PDF,批量填写并合并表格(是否开启智能模式)
    • 9.实现示例:第7章
      • 1)创建PDF,PDF/UA标准(快棕狐)
      • 2)创建PDF,PDF/A-1a标准(快棕狐)
      • 3)创建PDF,PDF/A-1b标准(快棕狐)
      • 4)创建PDF,PDF/A-3a标准(美国信息)
      • 5)根据PDF,合并PDF/A类文档(快棕狐+美国信息)

在这里插入图片描述

1.简介

iText: 是一个用于创建和处理 PDF 文件的开源 Java 库。它提供了一种在 Java 程序中创建和操作 PDF 文档的简单方法,并可以生成包含文本、表格、图像、列表和其他元素的PDF文件。

官网地址: https://itextpdf.com/

GitHub: https://github.com/itext

官方示例: https://itextpdf.com/demos

官方文档: https://wiki.itextsupport.com/home/it7kb/installation-guidelines/installing-itext-7-for-java

官网页面如下:

在这里插入图片描述

官网示例页面如下:

在这里插入图片描述

2.Maven依赖

注意:iText 5 已经停止更新了,推荐使用 iText 7

<properties><itext.version>7.2.5</itext.version>
</properties>
<dependencies><!-- iText 7 --><dependency><groupId>com.itextpdf</groupId><artifactId>itext7-core</artifactId><version>${itext.version}</version><type>pom</type></dependency>
</dependencies>

3.实现示例:第1章

代码地址:https://gitee.com/acgkaka/SpringBootExamples/tree/master/springboot-itext

代码涉及资源地址: https://gitee.com/acgkaka/SpringBootExamples/tree/master/springboot-itext/src/main/resources

官方示例文档地址: https://kb.itextpdf.com/home/it7kb/examples/itext-7-jump-start-tutorial-chapter-1

官方示例代码地址: https://github.com/itext/i7js-jumpstart

1)创建PDF文件,写入 Hello World

在这里插入图片描述

/*** 创建PDF,并写入Hello World*/
@GetMapping(value = "/helloWorld", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> helloWorld() {ByteArrayOutputStream outputStream = new ByteArrayOutputStream();PdfWriter writer = new PdfWriter(outputStream);PdfDocument pdfDocument = new PdfDocument(writer);Document document = new Document(pdfDocument);// 写入 Hello Worlddocument.add(new Paragraph("Hello World!"));document.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

2)创建PDF,定制字体并写入多行(Rick Astley 歌词)

在这里插入图片描述

/*** 创建PDF,定制字体并写入多行(Rick Astley 歌词)*/
@GetMapping(value = "/createPdfWithLines", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> createPdfWithLines() throws IOException {ByteArrayOutputStream outputStream = new ByteArrayOutputStream();PdfWriter writer = new PdfWriter(outputStream);PdfDocument pdfDocument = new PdfDocument(writer);Document document = new Document(pdfDocument);// 定制字体,并写入多行PdfFont font = PdfFontFactory.createFont(StandardFonts.TIMES_ROMAN);document.add(new Paragraph("iText is:").setFont(font));// import com.itextpdf.layout.element.ListList list = new List().setSymbolIndent(12).setListSymbol("\u2022").setFont(font);list.add(new ListItem("Never gonna give you up")).add(new ListItem("Never gonna let you down")).add(new ListItem("Never gonna run around and desert you")).add(new ListItem("Never gonna make you cry")).add(new ListItem("Never gonna say goodbye")).add(new ListItem("Never gonna tell a lie and hurt you"));document.add(list);document.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

3)创建PDF,定制字体并写入文字和图片(快棕狐)

在这里插入图片描述

/*** 创建PDF,定制字体并写入文字和图片(快棕狐)*/
@GetMapping(value = "/createPdfWithImg", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> createPdfWithImg() throws IOException {ByteArrayOutputStream outputStream = new ByteArrayOutputStream();PdfWriter writer = new PdfWriter(outputStream);PdfDocument pdfDocument = new PdfDocument(writer);Document document = new Document(pdfDocument);// 插入图片final String foxImgPath = "src/main/resources/img/fox.bmp";final String dogImgPath = "src/main/resources/img/dog.bmp";Image fox = new Image(ImageDataFactory.create(foxImgPath));Image dog = new Image(ImageDataFactory.create(dogImgPath));Paragraph p = new Paragraph("The quick brown ").add(fox).add(" jumps over the lazy ").add(dog);document.add(p);document.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

4)创建PDF,定制字体并根据csv文件写入表格(美国城市信息)

在这里插入图片描述

/*** 创建PDF,定制字体并根据csv文件写入表格(美国城市信息)*/
@GetMapping(value = "/createPdfWithTable", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> createPdfWithTable() throws IOException {final String data = "src/main/resources/data/united_states.csv";ByteArrayOutputStream outputStream = new ByteArrayOutputStream();PdfWriter writer = new PdfWriter(outputStream);PdfDocument pdfDocument = new PdfDocument(writer);Document document = new Document(pdfDocument, PageSize.A4.rotate());document.setMargins(20, 20, 20, 20);// 根据csv文件写入表格PdfFont font = PdfFontFactory.createFont(StandardFonts.HELVETICA);PdfFont bold = PdfFontFactory.createFont(StandardFonts.HELVETICA_BOLD);Table table = new Table(UnitValue.createPercentArray(new float[]{4, 1, 3, 4, 3, 3, 3, 3, 1})).useAllAvailableWidth();BufferedReader br = new BufferedReader(new FileReader(data));String line = br.readLine();process(table, line, bold, true);while ((line = br.readLine()) != null) {process(table, line, font, false);}br.close();document.add(table);document.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}/*** 处理表格* @param table 表格* @param line  csv中一行内容* @param font  字体* @param isHeader  是否是表头*/
private void process(Table table, String line, PdfFont font, boolean isHeader) {StringTokenizer tokenizer = new StringTokenizer(line, ";");while (tokenizer.hasMoreTokens()) {if (isHeader) {table.addHeaderCell(new Cell().add(new Paragraph(tokenizer.nextToken()).setFont(font)));} else {table.addCell(new Cell().add(new Paragraph(tokenizer.nextToken()).setFont(font)));}}
}

4.实现示例:第2章

1)创建PDF,画坐标轴

在这里插入图片描述

/*** 创建PDF,画坐标轴*/
@GetMapping(value = "/createPdfWithAxes", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> createPdfWithLines() {ByteArrayOutputStream outputStream = new ByteArrayOutputStream();PdfWriter writer = new PdfWriter(outputStream);PdfDocument pdf = new PdfDocument(writer);PageSize ps = PageSize.A4.rotate();PdfPage page = pdf.addNewPage(ps);PdfCanvas canvas = new PdfCanvas(page);// 把坐标系的原点放到页面中间canvas.concatMatrix(1, 0, 0, 1, ps.getWidth() / 2, ps.getHeight() / 2);drawAxes(canvas, ps);pdf.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}/*** 画坐标轴* @param canvas    画布* @param ps        页面大小*/
private void drawAxes(PdfCanvas canvas, PageSize ps) {// 画X轴canvas.moveTo(-(ps.getWidth() / 2 - 15), 0).lineTo(ps.getWidth() / 2 - 15, 0).stroke();// 画X轴箭头canvas.setLineJoinStyle(PdfCanvasConstants.LineJoinStyle.ROUND).moveTo(ps.getWidth() / 2 - 25, -10).lineTo(ps.getWidth() / 2 - 15, 0).lineTo(ps.getWidth() / 2 - 25, 10).stroke().setLineJoinStyle(PdfCanvasConstants.LineJoinStyle.MITER);// 画y轴canvas.moveTo(0, -(ps.getHeight() / 2 - 15)).lineTo(0, ps.getHeight() / 2 - 15).stroke();// 画Y轴箭头canvas.saveState().setLineJoinStyle(PdfCanvasConstants.LineJoinStyle.ROUND).moveTo(-10, ps.getHeight() / 2 - 25).lineTo(0, ps.getHeight() / 2 - 15).lineTo(10, ps.getHeight() / 2 - 25).stroke().restoreState();// 画X衬线for (int i = -((int) ps.getWidth() / 2 - 61); i < ((int) ps.getWidth() / 2 - 60); i += 40) {canvas.moveTo(i, 5).lineTo(i, -5);}// 画Y衬线for (int j = -((int) ps.getHeight() / 2 - 57); j < ((int) ps.getHeight() / 2 - 56); j += 40) {canvas.moveTo(5, j).lineTo(-5, j);}canvas.stroke();
}

2)创建PDF,画网格线

在这里插入图片描述

/*** 创建PDF,画网格线*/
@GetMapping(value = "/createPdfWithGridlines", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> createPdfWithGridlines(String dest) throws IOException {ByteArrayOutputStream outputStream = new ByteArrayOutputStream();PdfWriter writer = new PdfWriter(outputStream);PdfDocument pdf = new PdfDocument(writer);PageSize ps = PageSize.A4.rotate();PdfPage page = pdf.addNewPage(ps);PdfCanvas canvas = new PdfCanvas(page);// 把坐标系的原点放到页面中间canvas.concatMatrix(1, 0, 0, 1, ps.getWidth() / 2, ps.getHeight() / 2);Color grayColor = new DeviceCmyk(0.f, 0.f, 0.f, 0.875f);Color greenColor = new DeviceCmyk(1.f, 0.f, 1.f, 0.176f);Color blueColor = new DeviceCmyk(1.f, 0.156f, 0.f, 0.118f);canvas.setLineWidth(0.5f).setStrokeColor(blueColor);// 画水平网格线for (int i = -((int) ps.getHeight() / 2 - 57); i < ((int) ps.getHeight() / 2 - 56); i += 40) {canvas.moveTo(-(ps.getWidth() / 2 - 15), i).lineTo(ps.getWidth() / 2 - 15, i);}// 画垂直网格线for (int j = -((int) ps.getWidth() / 2 - 61); j < ((int) ps.getWidth() / 2 - 60); j += 40) {canvas.moveTo(j, -(ps.getHeight() / 2 - 15)).lineTo(j, ps.getHeight() / 2 - 15);}canvas.stroke();// 画轴canvas.setLineWidth(3).setStrokeColor(grayColor);drawAxes(canvas, ps);// 画虚线canvas.setLineWidth(2).setStrokeColor(greenColor).setLineDash(10, 10, 8).moveTo(-(ps.getWidth() / 2 - 15), -(ps.getHeight() / 2 - 15)).lineTo(ps.getWidth() / 2 - 15, ps.getHeight() / 2 - 15).stroke();pdf.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

3)创建PDF,写星球大战

在这里插入图片描述

/*** 创建PDF,并写星球大战*/
@GetMapping(value = "/createPdfWithStarWars", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> createPdfWithStarWars() throws IOException {ByteArrayOutputStream outputStream = new ByteArrayOutputStream();PdfWriter writer = new PdfWriter(outputStream);PdfDocument pdf = new PdfDocument(writer);//Add new pagePageSize ps = PageSize.A4;PdfPage page = pdf.addNewPage(ps);PdfCanvas canvas = new PdfCanvas(page);List<String> text = new ArrayList<>();text.add("         Episode V         ");text.add("  THE EMPIRE STRIKES BACK  ");text.add("It is a dark time for the");text.add("Rebellion. Although the Death");text.add("Star has been destroyed,");text.add("Imperial troops have driven the");text.add("Rebel forces from their hidden");text.add("base and pursued them across");text.add("the galaxy.");text.add("Evading the dreaded Imperial");text.add("Starfleet, a group of freedom");text.add("fighters led by Luke Skywalker");text.add("has established a new secret");text.add("base on the remote ice world");text.add("of Hoth...");//Replace the origin of the coordinate system to the top left cornercanvas.concatMatrix(1, 0, 0, 1, 0, ps.getHeight());canvas.beginText().setFontAndSize(PdfFontFactory.createFont(StandardFonts.COURIER_BOLD), 14).setLeading(14 * 1.2f).moveText(70, -40);for (String s : text) {//Add text and move to the next linecanvas.newlineShowText(s);}canvas.endText();pdf.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

4)创建PDF,写星球大战(滚动版)

在这里插入图片描述

/*** 创建PDF,并滚动写星球大战*/
@GetMapping(value = "/createPdfWithStarWarsCrawl", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> createPdfWithStarWarsCrawl() throws IOException {ByteArrayOutputStream outputStream = new ByteArrayOutputStream();PdfWriter writer = new PdfWriter(outputStream);PdfDocument pdf = new PdfDocument(writer);//Add new pagePageSize ps = PageSize.A4;PdfPage page = pdf.addNewPage(ps);List<String> text = new ArrayList();text.add("            Episode V      ");text.add("    THE EMPIRE STRIKES BACK  ");text.add("It is a dark time for the");text.add("Rebellion. Although the Death");text.add("Star has been destroyed,");text.add("Imperial troops have driven the");text.add("Rebel forces from their hidden");text.add("base and pursued them across");text.add("the galaxy.");text.add("Evading the dreaded Imperial");text.add("Starfleet, a group of freedom");text.add("fighters led by Luke Skywalker");text.add("has established a new secret");text.add("base on the remote ice world");text.add("of Hoth...");int maxStringWidth = 0;for (String fragment : text) {if (fragment.length() > maxStringWidth) {maxStringWidth = fragment.length();}}PdfCanvas canvas = new PdfCanvas(page);//Set black backgroundcanvas.rectangle(0, 0, ps.getWidth(), ps.getHeight()).setColor(ColorConstants.BLACK, true).fill();//Replace the origin of the coordinate system to the top left cornercanvas.concatMatrix(1, 0, 0, 1, 0, ps.getHeight());Color yellowColor = new DeviceCmyk(0.f, 0.0537f, 0.769f, 0.051f);float lineHeight = 5;float yOffset = -40;canvas.beginText().setFontAndSize(PdfFontFactory.createFont(StandardFonts.COURIER_BOLD), 1).setColor(yellowColor, true);for (int j = 0; j < text.size(); j++) {String line = text.get(j);float xOffset = ps.getWidth() / 2 - 45 - 8 * j;float fontSizeCoeff = 6 + j;float lineSpacing = (lineHeight + j) * j / 1.5f;int stringWidth = line.length();for (int i = 0; i < stringWidth; i++) {float angle = (maxStringWidth / 2 - i) / 2f;float charXOffset = (4 + (float) j / 2) * i;canvas.setTextMatrix(fontSizeCoeff, 0,angle, fontSizeCoeff / 1.5f,xOffset + charXOffset, yOffset - lineSpacing).showText(String.valueOf(line.charAt(i)));}}canvas.endText();//Close documentpdf.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

5.实现示例:第3章

注意:部分高级 PDF 功能需要使用 Adobe 才可以看到。

Adobe 官方下载地址: https://www.adobe.com/acrobat/pdf-reader.html

1)创建PDF,简单的列渲染示例(纽约时代周刊)

在这里插入图片描述

private static final String APPLE_IMG = "src/main/resources/img/ny_times_apple.jpg";
private static final String APPLE_TXT = "src/main/resources/data/ny_times_apple.txt";
private static final String FACEBOOK_IMG = "src/main/resources/img/ny_times_fb.jpg";
private static final String FACEBOOK_TXT = "src/main/resources/data/ny_times_fb.txt";
private static final String INST_IMG = "src/main/resources/img/ny_times_inst.jpg";
private static final String INST_TXT = "src/main/resources/data/ny_times_inst.txt";static PdfFont timesNewRoman = null;
static PdfFont timesNewRomanBold = null;/*** 创建PDF,简单的列渲染示例(纽约时代周刊)*/
@GetMapping(value = "/newYorkTimes", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> newYorkTimes() throws IOException {timesNewRoman = PdfFontFactory.createFont(StandardFonts.TIMES_ROMAN);timesNewRomanBold = PdfFontFactory.createFont(StandardFonts.TIMES_BOLD);ByteArrayOutputStream outputStream = new ByteArrayOutputStream();PdfWriter writer = new PdfWriter(outputStream);//Initialize PDF documentPdfDocument pdf = new PdfDocument(writer);PageSize ps = PageSize.A5;// Initialize documentDocument document = new Document(pdf, ps);//Set column parametersfloat offSet = 36;float columnWidth = (ps.getWidth() - offSet * 2 + 10) / 3;float columnHeight = ps.getHeight() - offSet * 2;//Define column areasRectangle[] columns = {new Rectangle(offSet - 5, offSet, columnWidth, columnHeight),new Rectangle(offSet + columnWidth, offSet, columnWidth, columnHeight),new Rectangle(offSet + columnWidth * 2 + 5, offSet, columnWidth, columnHeight)};document.setRenderer(new ColumnDocumentRenderer(document, columns));Image apple = new Image(ImageDataFactory.create(APPLE_IMG)).setWidth(columnWidth);String articleApple = new String(Files.readAllBytes(Paths.get(APPLE_TXT)), StandardCharsets.UTF_8);addArticle(document, "Apple Encryption Engineers, if Ordered to Unlock iPhone, Might Resist", "By JOHN MARKOFF MARCH 18, 2016", apple, articleApple);Image facebook = new Image(ImageDataFactory.create(FACEBOOK_IMG)).setWidth(columnWidth);String articleFB = new String(Files.readAllBytes(Paths.get(FACEBOOK_TXT)), StandardCharsets.UTF_8);addArticle(document, "With \"Smog Jog\" Through Beijing, Zuckerberg Stirs Debate on Air Pollution", "By PAUL MOZUR MARCH 18, 2016", facebook, articleFB);Image inst = new Image(ImageDataFactory.create(INST_IMG)).setWidth(columnWidth);String articleInstagram = new String(Files.readAllBytes(Paths.get(INST_TXT)), StandardCharsets.UTF_8);addArticle(document, "Instagram May Change Your Feed, Personalizing It With an Algorithm","By MIKE ISAAC MARCH 15, 2016", inst, articleInstagram);document.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}/*** 添加文章* @param doc       文档* @param title     标题* @param author    作者* @param img       图片* @param text      文本* @throws IOException IO异常*/
private static void addArticle(Document doc, String title, String author, Image img, String text) throws IOException {Paragraph p1 = new Paragraph(title).setFont(timesNewRomanBold).setFontSize(14);doc.add(p1);doc.add(img);Paragraph p2 = new Paragraph().setFont(timesNewRoman).setFontSize(7).setFontColor(ColorConstants.GRAY).add(author);doc.add(p2);Paragraph p3 = new Paragraph().setFont(timesNewRoman).setFontSize(10).add(text);doc.add(p3);
}

2)创建PDF,简单的表渲染示例(英格兰足球超级联赛)

在这里插入图片描述

Color greenColor = new DeviceCmyk(0.78f, 0, 0.81f, 0.21f);
Color yellowColor = new DeviceCmyk(0, 0, 0.76f, 0.01f);
Color redColor = new DeviceCmyk(0, 0.76f, 0.86f, 0.01f);
Color blueColor = new DeviceCmyk(0.28f, 0.11f, 0, 0);/*** 创建PDF,简单的表渲染示例(英格兰足球超级联赛)*/
@GetMapping(value = "/premierLeague", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> premierLeague() throws IOException {final String data = "src/main/resources/data/premier_league.csv";ByteArrayOutputStream outputStream = new ByteArrayOutputStream();PdfWriter writer = new PdfWriter(outputStream);//Initialize PDF documentPdfDocument pdf = new PdfDocument(writer);PageSize ps = new PageSize(842, 680);// Initialize documentDocument document = new Document(pdf, ps);PdfFont font = PdfFontFactory.createFont(StandardFonts.HELVETICA);PdfFont bold = PdfFontFactory.createFont(StandardFonts.HELVETICA_BOLD);Table table = new Table(UnitValue.createPercentArray(new float[]{1.5f, 7, 2, 2, 2, 2, 3, 4, 4, 2}));table.setTextAlignment(TextAlignment.CENTER).setHorizontalAlignment(HorizontalAlignment.CENTER);BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(data), StandardCharsets.UTF_8));String line = br.readLine();processTable1(table, line, bold, true);while ((line = br.readLine()) != null) {processTable1(table, line, font, false);}br.close();document.add(table);//Close documentdocument.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}/*** 处理表格* @param table     表格* @param line      行* @param font      字体* @param isHeader  是否是表头*/
private void processTable1(Table table, String line, PdfFont font, boolean isHeader) {StringTokenizer tokenizer = new StringTokenizer(line, ";");int columnNumber = 0;while (tokenizer.hasMoreTokens()) {if (isHeader) {Cell cell = new Cell().add(new Paragraph(tokenizer.nextToken()));cell.setNextRenderer(new RoundedCornersCellRenderer(cell));cell.setPadding(5).setBorder(null);table.addHeaderCell(cell);} else {columnNumber++;Cell cell = new Cell().add(new Paragraph(tokenizer.nextToken()));cell.setFont(font).setBorder(new SolidBorder(ColorConstants.BLACK, 0.5f));switch (columnNumber) {case 4:cell.setBackgroundColor(greenColor);break;case 5:cell.setBackgroundColor(yellowColor);break;case 6:cell.setBackgroundColor(redColor);break;default:cell.setBackgroundColor(blueColor);break;}table.addCell(cell);}}
}/*** 自定义渲染器*/
private class RoundedCornersCellRenderer extends CellRenderer {public RoundedCornersCellRenderer(Cell modelElement) {super(modelElement);}@Overridepublic void drawBorder(DrawContext drawContext) {Rectangle rectangle = getOccupiedAreaBBox();float llx = rectangle.getX() + 1;float lly = rectangle.getY() + 1;float urx = rectangle.getX() + getOccupiedAreaBBox().getWidth() - 1;float ury = rectangle.getY() + getOccupiedAreaBBox().getHeight() - 1;PdfCanvas canvas = drawContext.getCanvas();float r = 4;float b = 0.4477f;canvas.moveTo(llx, lly).lineTo(urx, lly).lineTo(urx, ury - r).curveTo(urx, ury - r * b, urx - r * b, ury, urx - r, ury).lineTo(llx + r, ury).curveTo(llx + r * b, ury, llx, ury - r * b, llx, ury - r).lineTo(llx, lly).stroke();super.drawBorder(drawContext);}
}

3)创建PDF,简单的事件渲染示例(UFO文件)

在这里插入图片描述

static PdfFont helvetica = null;
static PdfFont helveticaBold = null;/*** 创建PDF,简单的事件渲染示例(UFO文件)*/
@GetMapping(value = "/ufo", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> ufo() throws IOException {final String data = "src/main/resources/data/ufo.csv";helvetica = PdfFontFactory.createFont(StandardFonts.HELVETICA);helveticaBold = PdfFontFactory.createFont(StandardFonts.HELVETICA_BOLD);ByteArrayOutputStream outputStream = new ByteArrayOutputStream();PdfWriter writer = new PdfWriter(outputStream);//Initialize PDF documentPdfDocument pdf = new PdfDocument(writer);pdf.addEventHandler(PdfDocumentEvent.END_PAGE, new MyEventHandler());// Initialize documentDocument document = new Document(pdf);Paragraph p = new Paragraph("List of reported UFO sightings in 20th century").setTextAlignment(TextAlignment.CENTER).setFont(helveticaBold).setFontSize(14);document.add(p);Table table = new Table(UnitValue.createPercentArray(new float[]{3, 5, 7, 4}));BufferedReader br = new BufferedReader(new FileReader(data));String line = br.readLine();processTable2(table, line, helveticaBold, true);while ((line = br.readLine()) != null) {processTable2(table, line, helvetica, false);}br.close();document.add(table);document.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}/*** 处理表格* @param table     表格* @param line      行* @param font      字体* @param isHeader  是否是表头*/
private void processTable2(Table table, String line, PdfFont font, boolean isHeader) {StringTokenizer tokenizer = new StringTokenizer(line, ";");while (tokenizer.hasMoreTokens()) {if (isHeader) {table.addHeaderCell(new Cell().add(new Paragraph(tokenizer.nextToken()).setFont(font)).setFontSize(9).setBorder(new SolidBorder(ColorConstants.BLACK, 0.5f)));} else {table.addCell(new Cell().add(new Paragraph(tokenizer.nextToken()).setFont(font)).setFontSize(9).setBorder(new SolidBorder(ColorConstants.BLACK, 0.5f)));}}
}/*** 自定义事件处理器*/
private class MyEventHandler implements IEventHandler {public void handleEvent(Event event) {PdfDocumentEvent docEvent = (PdfDocumentEvent) event;PdfDocument pdfDoc = docEvent.getDocument();PdfPage page = docEvent.getPage();int pageNumber = pdfDoc.getPageNumber(page);Rectangle pageSize = page.getPageSize();PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdfDoc);//Set backgroundColor limeColor = new DeviceCmyk(0.208f, 0, 0.584f, 0);Color blueColor = new DeviceCmyk(0.445f, 0.0546f, 0, 0.0667f);pdfCanvas.saveState().setFillColor(pageNumber % 2 == 1 ? limeColor : blueColor).rectangle(pageSize.getLeft(), pageSize.getBottom(), pageSize.getWidth(), pageSize.getHeight()).fill().restoreState();//Add header and footerpdfCanvas.beginText().setFontAndSize(helvetica, 9).moveText(pageSize.getWidth() / 2 - 60, pageSize.getTop() - 20).showText("THE TRUTH IS OUT THERE").moveText(60, -pageSize.getTop() + 30).showText(String.valueOf(pageNumber)).endText();//Add watermarkCanvas canvas = new Canvas(pdfCanvas, page.getPageSize());canvas.setFontColor(ColorConstants.WHITE);canvas.setProperty(Property.FONT_SIZE, UnitValue.createPointValue(60));canvas.setProperty(Property.FONT, helveticaBold);canvas.showTextAligned(new Paragraph("CONFIDENTIAL"), 298, 421, pdfDoc.getPageNumber(page),TextAlignment.CENTER, VerticalAlignment.MIDDLE, 45);pdfCanvas.release();}
}

6.实现示例:第4章

1)创建PDF,添加文本批注

在这里插入图片描述

在这里插入图片描述

/*** 创建PDF,添加文本批注*/
@GetMapping(value = "/textAnnotation", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> textAnnotation() {ByteArrayOutputStream outputStream = new ByteArrayOutputStream();PdfWriter writer = new PdfWriter(outputStream);//Initialize PDF documentPdfDocument pdf = new PdfDocument(writer);//Initialize documentDocument document = new Document(pdf);document.add(new Paragraph("The example of text annotation."));//Create text annotationPdfAnnotation ann = new PdfTextAnnotation(new Rectangle(20, 800, 0, 0)).setOpen(true).setColor(ColorConstants.GREEN).setTitle(new PdfString("iText")).setContents("With iText, you can truly take your documentation needs to the next level.");pdf.getFirstPage().addAnnotation(ann);document.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

2)创建PDF,添加链接批注

在这里插入图片描述

/*** 创建PDF,添加链接批注*/
@GetMapping(value = "/linkAnnotation", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> linkAnnotation() {ByteArrayOutputStream outputStream = new ByteArrayOutputStream();PdfWriter writer = new PdfWriter(outputStream);//Initialize PDF documentPdfDocument pdf = new PdfDocument(writer);//Initialize documentDocument document = new Document(pdf);//Create link annotationPdfLinkAnnotation annotation = new PdfLinkAnnotation(new Rectangle(0, 0)).setAction(PdfAction.createURI("http://itextpdf.com/"));Link link = new Link("here", annotation);Paragraph p = new Paragraph("The example of link annotation. Click ").add(link.setUnderline()).add(" to learn more...");document.add(p);//Close documentdocument.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

3)创建PDF,添加线批注

(注意:这里不要用谷歌浏览器了,是看不到的)

在这里插入图片描述

/*** 创建PDF,添加线批注*/
@GetMapping(value = "/lineAnnotation", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> lineAnnotation() {ByteArrayOutputStream outputStream = new ByteArrayOutputStream();PdfWriter writer = new PdfWriter(outputStream);//Initialize PDF documentPdfDocument pdf = new PdfDocument(writer);PdfPage page = pdf.addNewPage();PdfArray lineEndings = new PdfArray();lineEndings.add(new PdfName("Diamond"));lineEndings.add(new PdfName("Diamond"));//Create line annotation with inside captionPdfAnnotation annotation = new PdfLineAnnotation(new Rectangle(0, 0),new float[]{20, 790, page.getPageSize().getWidth() - 20, 790}).setLineEndingStyles((lineEndings)).setContentsAsCaption(true).setTitle(new PdfString("iText")).setContents("The example of line annotation").setColor(ColorConstants.BLUE);page.addAnnotation(annotation);//Close documentpdf.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

4)创建PDF,添加文本标记批注

在这里插入图片描述

/*** 创建PDF,添加文本标记批注*/
@GetMapping(value = "/textMarkupAnnotation", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> textMarkupAnnotation() {ByteArrayOutputStream outputStream = new ByteArrayOutputStream();//Initialize PDF documentPdfDocument pdf = new PdfDocument(new PdfWriter(outputStream));//Initialize documentDocument document = new Document(pdf);Paragraph p = new Paragraph("The example of text markup annotation.");document.showTextAligned(p, 20, 795, 1, TextAlignment.LEFT,VerticalAlignment.MIDDLE, 0);//Create text markup annotationPdfAnnotation ann = PdfTextMarkupAnnotation.createHighLight(new Rectangle(105, 790, 64, 10),new float[]{169, 790, 105, 790, 169, 800, 105, 800}).setColor(ColorConstants.YELLOW).setTitle(new PdfString("Hello!")).setContents(new PdfString("I'm a popup.")).setTitle(new PdfString("iText")).setRectangle(new PdfArray(new float[]{100, 600, 200, 100}));pdf.getFirstPage().addAnnotation(ann);//Close documentdocument.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

5)创建PDF,添加简单组件的批注(职位申请表)

在这里插入图片描述

/*** Add acroform to the document* @param doc   document* @return      PdfAcroForm*/
private PdfAcroForm addAcroForm(Document doc) {Paragraph title = new Paragraph("Application for employment").setTextAlignment(TextAlignment.CENTER).setFontSize(16);doc.add(title);doc.add(new Paragraph("Full name:").setFontSize(12));doc.add(new Paragraph("Native language:      English         French       German        Russian        Spanish").setFontSize(12));doc.add(new Paragraph("Experience in:       cooking        driving           software development").setFontSize(12));doc.add(new Paragraph("Preferred working shift:").setFontSize(12));doc.add(new Paragraph("Additional information:").setFontSize(12));//Add acroformPdfAcroForm form = PdfAcroForm.getAcroForm(doc.getPdfDocument(), true);//Create text fieldPdfTextFormField nameField = PdfTextFormField.createText(doc.getPdfDocument(),new Rectangle(99, 753, 425, 15), "name", "");form.addField(nameField);//Create radio buttonsPdfButtonFormField group = PdfFormField.createRadioGroup(doc.getPdfDocument(), "language", "");PdfFormField.createRadioButton(doc.getPdfDocument(), new Rectangle(130, 728, 15, 15), group, "English");PdfFormField.createRadioButton(doc.getPdfDocument(), new Rectangle(200, 728, 15, 15), group, "French");PdfFormField.createRadioButton(doc.getPdfDocument(), new Rectangle(260, 728, 15, 15), group, "German");PdfFormField.createRadioButton(doc.getPdfDocument(), new Rectangle(330, 728, 15, 15), group, "Russian");PdfFormField.createRadioButton(doc.getPdfDocument(), new Rectangle(400, 728, 15, 15), group, "Spanish");form.addField(group);//Create checkboxesfor (int i = 0; i < 3; i++) {PdfButtonFormField checkField = PdfFormField.createCheckBox(doc.getPdfDocument(), new Rectangle(119 + i * 69, 701, 15, 15),"experience".concat(String.valueOf(i+1)), "Off", PdfFormField.TYPE_CHECK);form.addField(checkField);}//Create comboboxString[] options = {"Any", "6.30 am - 2.30 pm", "1.30 pm - 9.30 pm"};PdfChoiceFormField choiceField = PdfFormField.createComboBox(doc.getPdfDocument(), new Rectangle(163, 676, 115, 15),"shift", "Any", options);form.addField(choiceField);//Create multiline text fieldPdfTextFormField infoField = PdfTextFormField.createMultilineText(doc.getPdfDocument(),new Rectangle(158, 625, 366, 40), "info", "");form.addField(infoField);//Create push button fieldPdfButtonFormField button = PdfFormField.createPushButton(doc.getPdfDocument(),new Rectangle(479, 594, 45, 15), "reset", "RESET");button.setAction(PdfAction.createResetForm(new String[] {"name", "language", "experience1", "experience2", "experience3", "shift", "info"}, 0));form.addField(button);return form;}

6)创建PDF,添加并填充表单(职位申请表)

在这里插入图片描述

/*** 创建PDF,添加并填充表单(职位申请表)*/
@GetMapping(value = "/createAndFill", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> createAndFill() {ByteArrayOutputStream outputStream = new ByteArrayOutputStream();//Initialize PDF documentPdfDocument pdf = new PdfDocument(new PdfWriter(outputStream));// Initialize documentDocument doc = new Document(pdf);PdfAcroForm form = addAcroForm(doc);Map<String, PdfFormField> fields = form.getFormFields();fields.get("name").setValue("James Bond");fields.get("language").setValue("English");fields.get("experience1").setValue("Off");fields.get("experience2").setValue("Yes");fields.get("experience3").setValue("Yes");fields.get("shift").setValue("Any");fields.get("info").setValue("I was 38 years old when I became an MI6 agent.");doc.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

7)指定PDF,简单填充表单(职位申请表)

在这里插入图片描述

/*** 指定PDF,简单填写表单(职位申请表)*/
@GetMapping(value = "/flattenForm", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> flattenForm() throws IOException {final String src = "src/main/resources/pdf/job_application.pdf";ByteArrayOutputStream outputStream = new ByteArrayOutputStream();//Initialize PDF documentPdfDocument pdf = new PdfDocument(new PdfReader(src), new PdfWriter(outputStream));PdfAcroForm form = PdfAcroForm.getAcroForm(pdf, true);Map<String, PdfFormField> fields = form.getFormFields();fields.get("name").setValue("James Bond");fields.get("language").setValue("English");fields.get("experience1").setValue("Off");fields.get("experience2").setValue("Yes");fields.get("experience3").setValue("Yes");fields.get("shift").setValue("Any");fields.get("info").setValue("I was 38 years old when I became an MI6 agent.");form.flattenFields();pdf.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

7.实现示例:第5章

1)创建PDF,添加可回复型批注

在这里插入图片描述

/*** 创建PDF,添加可回复型批注*/
@GetMapping(value = "/addAnnotationAndContent", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> addAnnotationAndContent() throws IOException {final String src = "src/main/resources/pdf/job_application.pdf";ByteArrayOutputStream outputStream = new ByteArrayOutputStream();//Initialize PDF documentPdfDocument pdfDoc = new PdfDocument(new PdfReader(src), new PdfWriter(outputStream));//Add text annotationPdfAnnotation ann = new PdfTextAnnotation(new Rectangle(400, 795, 0, 0)).setOpen(true).setTitle(new PdfString("iText")).setContents("Please, fill out the form.");pdfDoc.getFirstPage().addAnnotation(ann);PdfCanvas canvas = new PdfCanvas(pdfDoc.getFirstPage());canvas.beginText().setFontAndSize(PdfFontFactory.createFont(StandardFonts.HELVETICA), 12).moveText(265, 597).showText("I agree to the terms and conditions.").endText();//Add form fieldPdfAcroForm form = PdfAcroForm.getAcroForm(pdfDoc, true);PdfButtonFormField checkField = PdfFormField.createCheckBox(pdfDoc, new Rectangle(245, 594, 15, 15),"agreement", "Off", PdfFormField.TYPE_CHECK);checkField.setRequired(true);form.addField(checkField);//Update reset buttonform.getField("reset").setAction(PdfAction.createResetForm(new String[]{"name", "language","experience1", "experience2", "experience3", "shift", "info", "agreement"}, 0));pdfDoc.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

2)根据PDF,填写并修改表单

在这里插入图片描述

/*** 根据PDF,填写并修改表单*/
@GetMapping(value = "/fillAndModifyForm", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> fillAndModifyForm() throws IOException {final String src = "src/main/resources/pdf/job_application.pdf";ByteArrayOutputStream outputStream = new ByteArrayOutputStream();//Initialize PDF documentPdfDocument pdfDoc = new PdfDocument(new PdfReader(src), new PdfWriter(outputStream));PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDoc, true);Map<String, PdfFormField> fields = form.getFormFields();fields.get("name").setValue("James Bond").setBackgroundColor(ColorConstants.ORANGE);fields.get("language").setValue("English");fields.get("experience1").setValue("Yes");fields.get("experience2").setValue("Yes");fields.get("experience3").setValue("Yes");List<PdfString> options = new ArrayList<PdfString>();options.add(new PdfString("Any"));options.add(new PdfString("8.30 am - 12.30 pm"));options.add(new PdfString("12.30 pm - 4.30 pm"));options.add(new PdfString("4.30 pm - 8.30 pm"));options.add(new PdfString("8.30 pm - 12.30 am"));options.add(new PdfString("12.30 am - 4.30 am"));options.add(new PdfString("4.30 am - 8.30 am"));PdfArray arr = new PdfArray(options);fields.get("shift").setOptions(arr);fields.get("shift").setValue("Any");PdfFont courier = PdfFontFactory.createFont(StandardFonts.COURIER);fields.get("info").setValue("I was 38 years old when I became an MI6 agent.", courier, 7f);pdfDoc.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

3)根据PDF,填充内容(页眉、页脚线、页脚页码、水印)

在这里插入图片描述

在这里插入图片描述

/*** 根据PDF,填充内容(页眉、页脚线、页脚页码、水印)*/
@GetMapping(value = "/addContent", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> addContent() throws IOException {final String src = "src/main/resources/pdf/ufo.pdf";ByteArrayOutputStream outputStream = new ByteArrayOutputStream();//Initialize PDF documentPdfDocument pdfDoc = new PdfDocument(new PdfReader(src), new PdfWriter(outputStream));Document document = new Document(pdfDoc);Rectangle pageSize;PdfCanvas canvas;int n = pdfDoc.getNumberOfPages();for (int i = 1; i <= n; i++) {PdfPage page = pdfDoc.getPage(i);pageSize = page.getPageSize();canvas = new PdfCanvas(page);// 画页眉文字canvas.beginText().setFontAndSize(PdfFontFactory.createFont(StandardFonts.HELVETICA), 7).moveText(pageSize.getWidth() / 2 - 24, pageSize.getHeight() - 10).showText("I want to believe").endText();// 画页脚线canvas.setStrokeColor(ColorConstants.BLACK).setLineWidth(.2f).moveTo(pageSize.getWidth() / 2 - 30, 20).lineTo(pageSize.getWidth() / 2 + 30, 20).stroke();// 画页码canvas.beginText().setFontAndSize(PdfFontFactory.createFont(StandardFonts.HELVETICA), 7).moveText(pageSize.getWidth() / 2 - 7, 10).showText(String.valueOf(i)).showText(" of ").showText(String.valueOf(n)).endText();// 画水印Paragraph p = new Paragraph("CONFIDENTIAL").setFontSize(60);canvas.saveState();PdfExtGState gs1 = new PdfExtGState().setFillOpacity(0.2f);canvas.setExtGState(gs1);document.showTextAligned(p,pageSize.getWidth() / 2, pageSize.getHeight() / 2,pdfDoc.getPageNumber(page),TextAlignment.CENTER, VerticalAlignment.MIDDLE, 45);canvas.restoreState();}pdfDoc.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

4)根据PDF,改变页面(大小、边框、旋转)

在这里插入图片描述

在这里插入图片描述

/*** 根据PDF,改变页面(大小、边框、旋转)*/
@GetMapping(value = "/changePage", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> changePage() throws IOException {final String src = "src/main/resources/pdf/ufo.pdf";ByteArrayOutputStream outputStream = new ByteArrayOutputStream();//Initialize PDF documentPdfDocument pdfDoc = new PdfDocument(new PdfReader(src), new PdfWriter(outputStream));float margin = 72;for (int i = 1; i <= pdfDoc.getNumberOfPages(); i++) {PdfPage page = pdfDoc.getPage(i);// change page sizeRectangle mediaBox = page.getMediaBox();Rectangle newMediaBox = new Rectangle(mediaBox.getLeft() - margin, mediaBox.getBottom() - margin,mediaBox.getWidth() + margin * 2, mediaBox.getHeight() + margin * 2);page.setMediaBox(newMediaBox);// add borderPdfCanvas over = new PdfCanvas(page);over.setStrokeColor(ColorConstants.GRAY);over.rectangle(mediaBox.getLeft(), mediaBox.getBottom(), mediaBox.getWidth(), mediaBox.getHeight());over.stroke();// change rotation of the even pagesif (i % 2 == 0) {page.setRotation(180);}}pdfDoc.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

8.实现示例:第6章

1)根据PDF,缩放尺寸(金门大桥)

在这里插入图片描述

/*** 根据PDF,缩放尺寸(金门大桥)*/
@GetMapping(value = "/theGoldenGateBridgeScaleShrink", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> createPdfWithLines() throws IOException {final String src = "src/main/resources/pdf/the_golden_gate_bridge.pdf";ByteArrayOutputStream outputStream = new ByteArrayOutputStream();//Initialize PDF documentPdfDocument pdf = new PdfDocument(new PdfWriter(outputStream));PdfDocument origPdf = new PdfDocument(new PdfReader(src));//Original page sizePdfPage origPage = origPdf.getPage(1);Rectangle orig = origPage.getPageSizeWithRotation();//Add A4 pagePdfPage page = pdf.addNewPage(PageSize.A4.rotate());//Shrink original page content using transformation matrixPdfCanvas canvas = new PdfCanvas(page);AffineTransform transformationMatrix = AffineTransform.getScaleInstance(page.getPageSize().getWidth() / orig.getWidth(), page.getPageSize().getHeight() / orig.getHeight());canvas.concatMatrix(transformationMatrix);PdfFormXObject pageCopy = origPage.copyAsFormXObject(pdf);canvas.addXObjectAt(pageCopy, 0, 0);//Add page with original sizepdf.addPage(origPage.copyTo(pdf));//Add A2 pagepage = pdf.addNewPage(PageSize.A2.rotate());//Scale original page content using transformation matrixcanvas = new PdfCanvas(page);transformationMatrix = AffineTransform.getScaleInstance(page.getPageSize().getWidth() / orig.getWidth(), page.getPageSize().getHeight() / orig.getHeight());canvas.concatMatrix(transformationMatrix);canvas.addXObjectAt(pageCopy, 0, 0);pdf.close();origPdf.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

2)根据PDF,一分为四(金门大桥)

在这里插入图片描述

/*** 根据PDF,一分为四(金门大桥)*/
@GetMapping(value = "/theGoldenGateBridgeTiles", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> theGoldenGateBridgeTiles() throws IOException {final String src = "src/main/resources/pdf/the_golden_gate_bridge.pdf";ByteArrayOutputStream outputStream = new ByteArrayOutputStream();//Initialize PDF documentPdfDocument pdf = new PdfDocument(new PdfWriter(outputStream));PdfDocument sourcePdf = new PdfDocument(new PdfReader(src));//Original pagePdfPage origPage = sourcePdf.getPage(1);PdfFormXObject pageCopy = origPage.copyAsFormXObject(pdf);//Original page sizeRectangle orig = origPage.getPageSize();//Tile sizeRectangle tileSize = PageSize.A4.rotate();// Transformation matrixAffineTransform transformationMatrix = AffineTransform.getScaleInstance(tileSize.getWidth() / orig.getWidth() * 2f, tileSize.getHeight() / orig.getHeight() * 2f);//The first tilePdfPage page = pdf.addNewPage(PageSize.A4.rotate());PdfCanvas canvas = new PdfCanvas(page);canvas.concatMatrix(transformationMatrix);canvas.addXObjectAt(pageCopy, 0, -orig.getHeight() / 2f);//The second tilepage = pdf.addNewPage(PageSize.A4.rotate());canvas = new PdfCanvas(page);canvas.concatMatrix(transformationMatrix);canvas.addXObjectAt(pageCopy, -orig.getWidth() / 2f, -orig.getHeight() / 2f);//The third tilepage = pdf.addNewPage(PageSize.A4.rotate());canvas = new PdfCanvas(page);canvas.concatMatrix(transformationMatrix);canvas.addXObjectAt(pageCopy, 0, 0);//The fourth tilepage = pdf.addNewPage(PageSize.A4.rotate());canvas = new PdfCanvas(page);canvas.concatMatrix(transformationMatrix);canvas.addXObjectAt(pageCopy, -orig.getWidth() / 2f, 0);pdf.close();sourcePdf.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

3)根据PDF,多页合并(金门大桥)

在这里插入图片描述

/*** 根据PDF,多页合并(金门大桥)*/
@GetMapping(value = "/theGoldenGateBridgeNUp", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> theGoldenGateBridgeNUp() throws IOException {final String src = "src/main/resources/pdf/the_golden_gate_bridge.pdf";ByteArrayOutputStream outputStream = new ByteArrayOutputStream();//Initialize PDF documentPdfDocument pdf = new PdfDocument(new PdfWriter(outputStream));PdfDocument sourcePdf = new PdfDocument(new PdfReader(src));//Original pagePdfPage origPage = sourcePdf.getPage(1);//Original page sizeRectangle orig = origPage.getPageSize();PdfFormXObject pageCopy = origPage.copyAsFormXObject(pdf);//N-up pagePageSize nUpPageSize = PageSize.A4.rotate();PdfPage page = pdf.addNewPage(nUpPageSize);PdfCanvas canvas = new PdfCanvas(page);//Scale pageAffineTransform transformationMatrix = AffineTransform.getScaleInstance(nUpPageSize.getWidth() / orig.getWidth() / 2f, nUpPageSize.getHeight() / orig.getHeight() / 2f);canvas.concatMatrix(transformationMatrix);//Add pages to N-up pagecanvas.addXObjectAt(pageCopy, 0, orig.getHeight());canvas.addXObjectAt(pageCopy, orig.getWidth(), orig.getHeight());canvas.addXObjectAt(pageCopy, 0, 0);canvas.addXObjectAt(pageCopy, orig.getWidth(), 0);pdf.close();sourcePdf.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

4)根据PDF,进行拼接(第88届奥斯卡)

在这里插入图片描述

/*** 根据PDF,进行拼接(第88届奥斯卡)*/
@GetMapping(value = "/the88thOscarCombine", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> the88thOscarCombine() throws IOException {final String src1 = "src/main/resources/pdf/88th_reminder_list.pdf";final String src2 = "src/main/resources/pdf/88th_noms_announcement.pdf";ByteArrayOutputStream outputStream = new ByteArrayOutputStream();//Initialize PDF document with output intentPdfDocument pdf = new PdfDocument(new PdfWriter(outputStream));PdfMerger merger = new PdfMerger(pdf);//Add pages from the first documentPdfDocument firstSourcePdf = new PdfDocument(new PdfReader(src1));merger.merge(firstSourcePdf, 1, firstSourcePdf.getNumberOfPages());//Add pages from the second pdf documentPdfDocument secondSourcePdf = new PdfDocument(new PdfReader(src2));merger.merge(secondSourcePdf, 1, secondSourcePdf.getNumberOfPages());firstSourcePdf.close();secondSourcePdf.close();pdf.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

5)根据PDF,抽取指定页数进行拼接(第88届奥斯卡)

在这里插入图片描述

在这里插入图片描述

/*** 根据PDF,抽取指定页数进行拼接(第88届奥斯卡)*/
@GetMapping(value = "/the88thOscarCombineXofY", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> the88thOscarCombineXofY() throws IOException {final String src1 = "src/main/resources/pdf/88th_reminder_list.pdf";final String src2 = "src/main/resources/pdf/88th_noms_announcement.pdf";ByteArrayOutputStream outputStream = new ByteArrayOutputStream();//Initialize PDF document with output intentPdfDocument pdf = new PdfDocument(new PdfWriter(outputStream));PdfMerger merger = new PdfMerger(pdf);//Add pages from the first documentPdfDocument firstSourcePdf = new PdfDocument(new PdfReader(src1));merger.merge(firstSourcePdf, Arrays.asList(1, 5, 7, 1));//Add pages from the second pdf documentPdfDocument secondSourcePdf = new PdfDocument(new PdfReader(src2));merger.merge(secondSourcePdf, Arrays.asList(1, 15));firstSourcePdf.close();secondSourcePdf.close();pdf.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

6)根据PDF,拼接并添加目录(第88届奥斯卡)

在这里插入图片描述

/*** 存储目录清单*/
private static final Map<String, Integer> TheRevenantNominations = new TreeMap<String, Integer>();
static {TheRevenantNominations.put("Performance by an actor in a leading role", 4);TheRevenantNominations.put("Performance by an actor in a supporting role", 4);TheRevenantNominations.put("Achievement in cinematography", 4);TheRevenantNominations.put("Achievement in costume design", 5);TheRevenantNominations.put("Achievement in directing", 5);TheRevenantNominations.put("Achievement in film editing", 6);TheRevenantNominations.put("Achievement in makeup and hairstyling", 7);TheRevenantNominations.put("Best motion picture of the year", 8);TheRevenantNominations.put("Achievement in production design", 8);TheRevenantNominations.put("Achievement in sound editing", 9);TheRevenantNominations.put("Achievement in sound mixing", 9);TheRevenantNominations.put("Achievement in visual effects", 10);
}/*** 根据PDF,拼接并添加目录(第88届奥斯卡)*/
@GetMapping(value = "/the88thOscarCombineAddTOC", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> the88thOscarCombineAddTOC() throws IOException {final String src1 = "src/main/resources/pdf/88th_noms_announcement.pdf";final String src2 = "src/main/resources/pdf/oscars_movies_checklist_2016.pdf";ByteArrayOutputStream outputStream = new ByteArrayOutputStream();PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outputStream));Document document = new Document(pdfDoc);document.add(new Paragraph(new Text("The Revenant nominations list")).setTextAlignment(TextAlignment.CENTER));PdfDocument firstSourcePdf = new PdfDocument(new PdfReader(src1));for (Map.Entry<String, Integer> entry : TheRevenantNominations.entrySet()) {//Copy pagePdfPage page  = firstSourcePdf.getPage(entry.getValue()).copyTo(pdfDoc);pdfDoc.addPage(page);//Overwrite page numberText text = new Text(String.format("Page %d", pdfDoc.getNumberOfPages() - 1));text.setBackgroundColor(ColorConstants.WHITE);document.add(new Paragraph(text).setFixedPosition(pdfDoc.getNumberOfPages(), 549, 742, 100));//Add destinationString destinationKey = "p" + (pdfDoc.getNumberOfPages() - 1);PdfArray destinationArray = new PdfArray();destinationArray.add(page.getPdfObject());destinationArray.add(PdfName.XYZ);destinationArray.add(new PdfNumber(0));destinationArray.add(new PdfNumber(page.getMediaBox().getHeight()));destinationArray.add(new PdfNumber(1));pdfDoc.addNamedDestination(destinationKey, destinationArray);//Add TOC line with bookmarkParagraph p = new Paragraph();p.addTabStops(new TabStop(540, TabAlignment.RIGHT, new DottedLine()));p.add(entry.getKey());p.add(new Tab());p.add(String.valueOf(pdfDoc.getNumberOfPages() - 1));p.setProperty(Property.ACTION, PdfAction.createGoTo(destinationKey));document.add(p);}firstSourcePdf.close();//Add the last pagePdfDocument secondSourcePdf = new PdfDocument(new PdfReader(src2));PdfPage page  = secondSourcePdf.getPage(1).copyTo(pdfDoc);pdfDoc.addPage(page);//Add destinationPdfArray destinationArray = new PdfArray();destinationArray.add(page.getPdfObject());destinationArray.add(PdfName.XYZ);destinationArray.add(new PdfNumber(0));destinationArray.add(new PdfNumber(page.getMediaBox().getHeight()));destinationArray.add(new PdfNumber(1));pdfDoc.addNamedDestination("checklist", destinationArray);//Add TOC line with bookmarkParagraph p = new Paragraph();p.addTabStops(new TabStop(540, TabAlignment.RIGHT, new DottedLine()));p.add("Oscars\u00ae 2016 Movie Checklist");p.add(new Tab());p.add(String.valueOf(pdfDoc.getNumberOfPages() - 1));p.setProperty(Property.ACTION, PdfAction.createGoTo("checklist"));document.add(p);secondSourcePdf.close();// close the documentdocument.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

7)根据PDF,合并表格

在这里插入图片描述

/*** 根据PDF,合并表格*/
@GetMapping(value = "/combineForms", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> combineForms() throws IOException {final String src1 = "src/main/resources/pdf/subscribe.pdf";final String src2 = "src/main/resources/pdf/state.pdf";ByteArrayOutputStream outputStream = new ByteArrayOutputStream();PdfDocument destPdfDocument = new PdfDocument(new PdfWriter(outputStream));PdfDocument[] sources = new PdfDocument[] {new PdfDocument(new PdfReader(src1)),new PdfDocument(new PdfReader(src2))};PdfPageFormCopier formCopier = new PdfPageFormCopier();for (PdfDocument sourcePdfDocument : sources) {sourcePdfDocument.copyPagesTo(1, sourcePdfDocument.getNumberOfPages(),destPdfDocument, formCopier);sourcePdfDocument.close();}destPdfDocument.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

8)根据PDF,批量填写并合并表格

在这里插入图片描述

/*** 根据PDF,批量填写并合并表格*/
@GetMapping(value = "/fillOutAndMergeForms", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> fillOutAndMergeForms() throws IOException {final String src = "src/main/resources/pdf/state.pdf";final String data = "src/main/resources/data/united_states.csv";ByteArrayOutputStream outputStream = new ByteArrayOutputStream();PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outputStream));PdfPageFormCopier formCopier = new PdfPageFormCopier();BufferedReader bufferedReader = new BufferedReader(new FileReader(data));String line;boolean headerLine = true;int i = 1;while ((line = bufferedReader.readLine()) != null) {if (headerLine) {headerLine = false;continue;}com.itextpdf.io.source.ByteArrayOutputStream baos = new com.itextpdf.io.source.ByteArrayOutputStream();PdfDocument sourcePdfDocument = new PdfDocument(new PdfReader(src), new PdfWriter(baos));//Rename fieldsi++;PdfAcroForm form = PdfAcroForm.getAcroForm(sourcePdfDocument, true);form.renameField("name", "name_" + i);form.renameField("abbr", "abbr_" + i);form.renameField("capital", "capital_" + i);form.renameField("city", "city_" + i);form.renameField("population", "population_" + i);form.renameField("surface", "surface_" + i);form.renameField("timezone1", "timezone1_" + i);form.renameField("timezone2", "timezone2_" + i);form.renameField("dst", "dst_" + i);//Fill out fieldsStringTokenizer tokenizer = new StringTokenizer(line, ";");Map<String, PdfFormField> fields = form.getFormFields();fields.get("name_" + i).setValue(tokenizer.nextToken());fields.get("abbr_" + i).setValue(tokenizer.nextToken());fields.get("capital_" + i).setValue(tokenizer.nextToken());fields.get("city_" + i).setValue(tokenizer.nextToken());fields.get("population_" + i).setValue(tokenizer.nextToken());fields.get("surface_" + i).setValue(tokenizer.nextToken());fields.get("timezone1_" + i).setValue(tokenizer.nextToken());fields.get("timezone2_" + i).setValue(tokenizer.nextToken());fields.get("dst_" + i).setValue(tokenizer.nextToken());sourcePdfDocument.close();sourcePdfDocument = new PdfDocument(new PdfReader(new ByteArrayInputStream(baos.toByteArray())));//Copy pagessourcePdfDocument.copyPagesTo(1, sourcePdfDocument.getNumberOfPages(), pdfDocument, formCopier);sourcePdfDocument.close();}bufferedReader.close();pdfDocument.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

9)根据PDF,批量填写并合并表格(是否开启智能模式)

  • 在智能模式下,当遇到资源(如字体、图像等)时,对这些资源的引用将保存在缓存中,以便可以重复使用。这需要更多内存,但会减小生成的 PDF 文档的文件大小。
  • 参见:https://api.itextpdf.com/iText7/java/7.1.14/com/itextpdf/kernel/pdf/PdfWriter.html#setSmartMode-boolean-

在这里插入图片描述

在这里插入图片描述

/*** 根据PDF,批量填写并合并表格(是否开启智能模式)*/
@GetMapping(value = "/fillOutFlattenAndMergeForms", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> fillOutFlattenAndMergeForms(boolean isSmartMode) throws IOException {final String src = "src/main/resources/pdf/state.pdf";final String data = "src/main/resources/data/united_states.csv";ByteArrayOutputStream outputStream = new ByteArrayOutputStream();PdfDocument destPdfDocument;if (isSmartMode) {// 在智能模式下,当遇到资源(如字体、图像等)时,对这些资源的引用将保存在缓存中,以便可以重复使用。这需要更多内存,但会减小生成的 PDF 文档的文件大小。// 参见:https://api.itextpdf.com/iText7/java/7.1.14/com/itextpdf/kernel/pdf/PdfWriter.html#setSmartMode-boolean-destPdfDocument = new PdfDocument(new PdfWriter(outputStream).setSmartMode(true));} else {destPdfDocument = new PdfDocument(new PdfWriter(outputStream));}BufferedReader bufferedReader = new BufferedReader(new FileReader(data));String line;boolean headerLine = true;while ((line = bufferedReader.readLine()) != null) {if (headerLine) {headerLine = false;continue;}com.itextpdf.io.source.ByteArrayOutputStream baos = new com.itextpdf.io.source.ByteArrayOutputStream();PdfDocument sourcePdfDocument = new PdfDocument(new PdfReader(src), new PdfWriter(baos));//Read fieldsPdfAcroForm form = PdfAcroForm.getAcroForm(sourcePdfDocument, true);StringTokenizer tokenizer = new StringTokenizer(line, ";");Map<String, PdfFormField> fields = form.getFormFields();//Fill out fieldsfields.get("name").setValue(tokenizer.nextToken());fields.get("abbr").setValue(tokenizer.nextToken());fields.get("capital").setValue(tokenizer.nextToken());fields.get("city").setValue(tokenizer.nextToken());fields.get("population").setValue(tokenizer.nextToken());fields.get("surface").setValue(tokenizer.nextToken());fields.get("timezone1").setValue(tokenizer.nextToken());fields.get("timezone2").setValue(tokenizer.nextToken());fields.get("dst").setValue(tokenizer.nextToken());//Flatten fieldsform.flattenFields();sourcePdfDocument.close();sourcePdfDocument = new PdfDocument(new PdfReader(new ByteArrayInputStream(baos.toByteArray())));//Copy pagessourcePdfDocument.copyPagesTo(1, sourcePdfDocument.getNumberOfPages(), destPdfDocument, null);sourcePdfDocument.close();}bufferedReader.close();destPdfDocument.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

9.实现示例:第7章

1)创建PDF,PDF/UA标准(快棕狐)

PDF/UA: 代表 “PDF Universal Accessibility”,是一种 PDF 文档的标准格式。PDF/UA 标准要求文档具有元数据、书签、标题、语言表示、图像说明、超链接等功能,以及通过 PDF/UA 验证工具进行验证,以确保其符合标准。这使得 PDF/UA 成为在企业、政府机构和组织内部以及对外发布重要文档时的首选格式。

在这里插入图片描述

/*** 创建PDF,PDF/UA标准(快棕狐)*/
@GetMapping(value = "/quickBrownFoxPDFUA", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> quickBrownFoxPDFUA() throws IOException {final String dog = "src/main/resources/img/dog.bmp";final String fox = "src/main/resources/img/fox.bmp";final String myFont = "src/main/resources/font/FreeSans.ttf";ByteArrayOutputStream outputStream = new ByteArrayOutputStream();PdfDocument pdf = new PdfDocument(new PdfWriter(outputStream, new WriterProperties().addUAXmpMetadata()));Document document = new Document(pdf);//Setting some required parameterspdf.setTagged();pdf.getCatalog().setLang(new PdfString("en-US"));pdf.getCatalog().setViewerPreferences(new PdfViewerPreferences().setDisplayDocTitle(true));PdfDocumentInfo info = pdf.getDocumentInfo();info.setTitle("iText7 PDF/UA example");//Fonts need to be embeddedPdfFont font = PdfFontFactory.createFont(myFont, PdfEncodings.WINANSI, PdfFontFactory.EmbeddingStrategy.FORCE_EMBEDDED);Paragraph p = new Paragraph();p.setFont(font);p.add(new Text("The quick brown "));Image foxImage = new Image(ImageDataFactory.create(fox));//PDF/UA: Set alt textfoxImage.getAccessibilityProperties().setAlternateDescription("Fox");p.add(foxImage);p.add(" jumps over the lazy ");Image dogImage = new Image(ImageDataFactory.create(dog));//PDF/UA: Set alt textdogImage.getAccessibilityProperties().setAlternateDescription("Dog");p.add(dogImage);document.add(p);document.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

2)创建PDF,PDF/A-1a标准(快棕狐)

PDF/A: 是为了长期保存和存档而设计的一种PDF文件格式。其中,PDF/A-1a、PDF/A-1b和PDF/A-3a是PDF/A格式的三种子格式。

PDF/A-1a: 要求PDF文档必须包含所有必要的元数据,且必须是无障碍的(即所有文本必须是可选择和可复制的),并且不允许使用高级功能,如JavaScript和交互式表单等。PDF/A-1a通常用于长期保存和存档需要,例如政府文档、法律文件、金融报告等。

在这里插入图片描述

/*** 创建PDF,PDF/A-1a标准(快棕狐)*/
@GetMapping(value = "/quickBrownFoxPDFA_1a", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> quickBrownFoxPDFA_1a() throws IOException {final String dog = "src/main/resources/img/dog.bmp";final String fox = "src/main/resources/img/fox.bmp";final String myFont = "src/main/resources/font/FreeSans.ttf";final String intent = "src/main/resources/color/sRGB_CS_profile.icm";ByteArrayOutputStream outputStream = new ByteArrayOutputStream();//Initialize PDFA document with output intentPdfADocument pdf = new PdfADocument(new PdfWriter(outputStream),PdfAConformanceLevel.PDF_A_1A,new PdfOutputIntent("Custom", "", "http://www.color.org","sRGB IEC61966-2.1", new FileInputStream(intent)));Document document = new Document(pdf);//Setting some required parameterspdf.setTagged();//Fonts need to be embeddedPdfFont font = PdfFontFactory.createFont(myFont, PdfEncodings.WINANSI, PdfFontFactory.EmbeddingStrategy.FORCE_EMBEDDED);Paragraph p = new Paragraph();p.setFont(font);p.add(new Text("The quick brown "));Image foxImage = new Image(ImageDataFactory.create(fox));//Set alt textfoxImage.getAccessibilityProperties().setAlternateDescription("Fox");p.add(foxImage);p.add(" jumps over the lazy ");Image dogImage = new Image(ImageDataFactory.create(dog));//Set alt textdogImage.getAccessibilityProperties().setAlternateDescription("Dog");p.add(dogImage);document.add(p);document.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

3)创建PDF,PDF/A-1b标准(快棕狐)

PDF/A-1b: PDF文档需要包含必要的元数据,但不需要无障碍性,且不允许使用JavaScript和其他高级功能。PDF/A-1b通常用于长期保存和存档需要,例如企业文件、技术文档等。

在这里插入图片描述

/*** 创建PDF,PDF/A-1b标准(快棕狐)*/
@GetMapping(value = "/quickBrownFoxPDFA_1b", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> quickBrownFoxPDFA_1b() throws IOException {final String dog = "src/main/resources/img/dog.bmp";final String fox = "src/main/resources/img/fox.bmp";final String myFont = "src/main/resources/font/FreeSans.ttf";final String intent = "src/main/resources/color/sRGB_CS_profile.icm";ByteArrayOutputStream outputStream = new ByteArrayOutputStream();//Initialize PDFA document with output intentPdfADocument pdf = new PdfADocument(new PdfWriter(outputStream),PdfAConformanceLevel.PDF_A_1B,new PdfOutputIntent("Custom", "", "http://www.color.org","sRGB IEC61966-2.1", new FileInputStream(intent)));Document document = new Document(pdf);//Fonts need to be embeddedPdfFont font = PdfFontFactory.createFont(myFont, PdfEncodings.WINANSI, PdfFontFactory.EmbeddingStrategy.FORCE_EMBEDDED);Paragraph p = new Paragraph();p.setFont(font);p.add(new Text("The quick brown "));Image foxImage = new Image(ImageDataFactory.create(fox));p.add(foxImage);p.add(" jumps over the lazy ");Image dogImage = new Image(ImageDataFactory.create(dog));p.add(dogImage);document.add(p);document.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

4)创建PDF,PDF/A-3a标准(美国信息)

PDF/A-3a: 允许将其他文件类型(如XML、CSV、JPEG等)嵌入到PDF文档中,同时保持PDF/A的规范和限制。PDF/A-3a通常用于长期保存和存档需要,例如电子发票、电子合同、电子档案等。

在这里插入图片描述

总之,PDF/A-1aPDF/A-1bPDF/A-3a 都是为了长期保存和存档而设计的 PDF 文件格式,它们各自具有特定的规范和限制,以确保文件的可靠性和一致性,同时也方便文档的长期保存和存档。

/*** 创建PDF,PDF/A-3a标准(快棕狐)*/
@GetMapping(value = "/quickBrownFoxPDFA_3a", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> quickBrownFoxPDFA_3a() throws IOException {final String data = "src/main/resources/data/united_states.csv";final String myFont = "src/main/resources/font/FreeSans.ttf";final String boldFont = "src/main/resources/font/FreeSansBold.ttf";final String intent = "src/main/resources/color/sRGB_CS_profile.icm";ByteArrayOutputStream outputStream = new ByteArrayOutputStream();PdfADocument pdf = new PdfADocument(new PdfWriter(outputStream),PdfAConformanceLevel.PDF_A_3A,new PdfOutputIntent("Custom", "", "http://www.color.org","sRGB IEC61966-2.1", new FileInputStream(intent)));Document document = new Document(pdf, PageSize.A4.rotate());document.setMargins(20, 20, 20, 20);//Setting some required parameterspdf.setTagged();pdf.getCatalog().setLang(new PdfString("en-US"));pdf.getCatalog().setViewerPreferences(new PdfViewerPreferences().setDisplayDocTitle(true));PdfDocumentInfo info = pdf.getDocumentInfo();info.setTitle("iText7 PDF/A-3 example");//Add attachmentPdfDictionary parameters = new PdfDictionary();parameters.put(PdfName.ModDate, new PdfDate().getPdfObject());PdfFileSpec fileSpec = PdfFileSpec.createEmbeddedFileSpec(pdf, Files.readAllBytes(Paths.get(data)), "united_states.csv","united_states.csv", new PdfName("text/csv"), parameters,PdfName.Data);fileSpec.put(new PdfName("AFRelationship"), new PdfName("Data"));pdf.addFileAttachment("united_states.csv", fileSpec);PdfArray array = new PdfArray();array.add(fileSpec.getPdfObject().getIndirectReference());pdf.getCatalog().put(new PdfName("AF"), array);//Embed fontsPdfFont font = PdfFontFactory.createFont(myFont, PdfFontFactory.EmbeddingStrategy.FORCE_EMBEDDED);PdfFont bold = PdfFontFactory.createFont(boldFont, PdfFontFactory.EmbeddingStrategy.FORCE_EMBEDDED);// Create contentTable table = new Table(UnitValue.createPercentArray(new float[]{4, 1, 3, 4, 3, 3, 3, 3, 1})).useAllAvailableWidth();BufferedReader br = new BufferedReader(new FileReader(data));String line = br.readLine();process(table, line, bold, true);while ((line = br.readLine()) != null) {process(table, line, font, false);}br.close();document.add(table);//Close documentdocument.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}public void process(Table table, String line, PdfFont font, boolean isHeader) {StringTokenizer tokenizer = new StringTokenizer(line, ";");while (tokenizer.hasMoreTokens()) {if (isHeader) {table.addHeaderCell(new Cell().setHorizontalAlignment(HorizontalAlignment.CENTER).add(new Paragraph(tokenizer.nextToken()).setHorizontalAlignment(HorizontalAlignment.CENTER).setFont(font)));} else {table.addCell(new Cell().setHorizontalAlignment(HorizontalAlignment.CENTER).add(new Paragraph(tokenizer.nextToken()).setHorizontalAlignment(HorizontalAlignment.CENTER).setFont(font)));}}
}

5)根据PDF,合并PDF/A类文档(快棕狐+美国信息)

在这里插入图片描述

/*** 根据PDF,合并PDF/A类文档*/
@GetMapping(value = "/mergePDFADocuments", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> mergePDFADocuments() throws IOException {final String intent = "src/main/resources/color/sRGB_CS_profile.icm";final String src1 = "src/main/resources/pdf/quick_brown_fox_PDFA-1a.pdf";final String src2 = "src/main/resources/pdf/united_states_PDFA-1a.pdf";ByteArrayOutputStream outputStream = new ByteArrayOutputStream();//Initialize PDFA document with output intentPdfADocument pdf = new PdfADocument(new PdfWriter(outputStream),PdfAConformanceLevel.PDF_A_1A,new PdfOutputIntent("Custom", "", "http://www.color.org","sRGB IEC61966-2.1", new FileInputStream(intent)));//Setting some required parameterspdf.setTagged();pdf.getCatalog().setLang(new PdfString("en-US"));pdf.getCatalog().setViewerPreferences(new PdfViewerPreferences().setDisplayDocTitle(true));PdfDocumentInfo info = pdf.getDocumentInfo();info.setTitle("iText7 PDF/A-1a example");//Create PdfMerger instancePdfMerger merger = new PdfMerger(pdf);//Add pages from the first documentPdfDocument firstSourcePdf = new PdfDocument(new PdfReader(src1));merger.merge(firstSourcePdf, 1, firstSourcePdf.getNumberOfPages());//Add pages from the second pdf documentPdfDocument secondSourcePdf = new PdfDocument(new PdfReader(src2));merger.merge(secondSourcePdf, 1, secondSourcePdf.getNumberOfPages());//Close the documentsfirstSourcePdf.close();secondSourcePdf.close();pdf.close();// 设置响应头HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "inline; filename=hello.pdf");return ResponseEntity.ok().headers(headers).contentType(MediaType.APPLICATION_PDF).body(outputStream.toByteArray());
}

整理完毕,完结撒花~ 🌻

这篇关于SpringBoot实战(十六)集成iText的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/741285

相关文章

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置