hi,欢迎访问本站!
当前位置: 首页学习笔记正文

java使用itext7生成pdf

用户投稿 学习笔记 11阅读
About itext

在网上看到java关于pdf的第三方库有名的是com.itextpdf的。 

上git上查看,官网的意思是推荐itext7,而itext5只用于修复bug和安全了:

GitHub - itext/itextpdf: [DEPRECATED] Core Java Library + PDF/A, xtra and XML Worker. Only security fixes will be added — please use iText 7[DEPRECATED] Core Java Library + PDF/A, xtra and XML Worker. Only security fixes will be added — please use iText 7 - GitHub - itext/itextpdf: [DEPRECATED] Core Java Library + PDF/A, xtra and XML Worker. Only security fixes will be added — please use iText 7https://github.com/itext/itextpdf

所以,下面是以itext7进行的开发 :

GitHub - itext/itext7: iText 7 for Java represents the next level of SDKs for developers that want to take advantage of the benefits PDF can bring. Equipped with a better document engine, high and low-level programming capabilities and the ability to create, edit and enhance PDF documents, iText 7 can be a boon to nearly every workflow.https://github.com/itext/itext7官网:

The Leading PDF Library for Developers | iTexthttps://itextpdf.com/en

API Doc

Demo

好的,接下里开始上demo:

布局设定

分为title、table、detail三大类,如下用绿色框出来了:

按照这个设定封装对应的数据载体

然后编写工具类

接下测试即可。  

工具类 imageUtil

用于读取base64的图片到byte数组

import org.bouncycastle.util.encoders.Base64;import javax.imageio.ImageIO;import java.awt.image.BufferedImage;import java.io.ByteArrayInputStream;import java.io.IOException;public class ImageUtil { /** * 校验base64是否合法 * @param base64 * @return */ public static boolean safeCheckImgFile(String base64) { //check image String regex = ","; String[] split = base64.split(regex); String imageBase64 = split[1]; byte[] decode = Base64.decode(imageBase64); ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(decode); try { BufferedImage image = ImageIO.read(byteArrayInputStream); if (image != null && image.getWidth() > 0 && image.getHeight() > 0) { return true; } } catch (IOException e) { e.printStackTrace(); } return false; /* Base64Encoder base64Encoder = new Base64Encoder(); try { FileOutputStream fileImageOutputStream = new FileOutputStream("/data/temp/"); BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileImageOutputStream); base64Encoder.decode(img, bufferedOutputStream); } catch (IOException e) { e.printStackTrace(); }*/ } /** * 读取base64字符串,转换为bimage的ytes数组并返回 * @param base64 * @return */ public static byte[] readFromImage(String base64) { String regex = ","; String[] split = base64.split(regex); String imageBase64 = split[1]; byte[] decode = Base64.decode(imageBase64); /* ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(decode); try { BufferedImage image = ImageIO.read(byteArrayInputStream);// System.out.println(image); } catch (IOException e) { e.printStackTrace(); }*/ return decode; }} PdfUtil_v2

Pdf生成工具

import com.itextpdf.io.image.ImageDataFactory;import com.itextpdf.kernel.colors.ColorConstants;import com.itextpdf.kernel.font.PdfFont;import com.itextpdf.kernel.font.PdfFontFactory;import com.itextpdf.kernel.pdf.PdfDocument;import com.itextpdf.kernel.pdf.PdfWriter;import com.itextpdf.layout.Document;import com.itextpdf.layout.borders.Border;import com.itextpdf.layout.borders.SolidBorder;import com.itextpdf.layout.element.Cell;import com.itextpdf.layout.element.Image;import com.itextpdf.layout.element.Paragraph;import com.itextpdf.layout.element.Table;import com.itextpdf.layout.properties.TextAlignment;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.io.File;import java.io.IOException;import java.net.MalformedURLException;import java.text.SimpleDateFormat;import java.util.LinkedList;import java.util.List;public class PdfUtil_v2 { private Logger logger = LoggerFactory.getLogger(PdfUtil_v2.class); private MyPdfDocument pdfDocumnt; private String file_PATH;//文件绝对路径,包含文件名和后缀,如:I:\\jfqqqq\\test\\1.pdf private String font_PATH; private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); private String font_INTERNAL_PATH; public PdfUtil_v2(MyPdfDocument pdfDocumnt, String file_PATH, String font_PATH) { this.pdfDocumnt = pdfDocumnt; this.file_PATH = file_PATH; this.font_PATH = font_PATH; File directory = new File("src/main/resources"); try { String resourcesPath = directory.getCanonicalPath(); font_INTERNAL_PATH = resourcesPath + "/fonts/SimSun-01.ttf"; logger.debug("配置的字体地址:{}, 工程预备的字体地址:{}", font_PATH, font_INTERNAL_PATH); } catch (IOException e) { e.printStackTrace(); } } /** * 生成pdf,注意:会覆盖 * * @return */ public File generate() { Document document = null; try { createFilePath(file_PATH, false); PdfWriter pdfWriter = new PdfWriter(file_PATH); PdfDocument pdfDocument = new PdfDocument(pdfWriter); PdfFont font = getPdfFont();//PdfFontFactory.createFont(font_PATH); document = new Document(pdfDocument).setFont(font); writeHeader(document); writeStaticsGrid(document); staticsDetails(document);// document.close(); return new File(file_PATH);// } } catch (Exception e) { e.printStackTrace(); } finally { if (document != null) { document.close(); } } return null; } private PdfFont getPdfFont() { PdfFont font = null; try { font = PdfFontFactory.createFont(font_PATH); } catch (IOException e) { logger.error("{} 字体文件不存在!即将采用更称默认字体,默认路径:{}", font_PATH, font_INTERNAL_PATH); synchronized (this) { font_PATH = font_INTERNAL_PATH; } } if (font == null) { try { font = PdfFontFactory.createFont(font_PATH); } catch (IOException e) { logger.error("{} 默认的字体文件不存在!即将采用itext7默认内置字体!不支持中文!", font_INTERNAL_PATH); } } if (font == null) { try { font = PdfFontFactory.createFont(); } catch (IOException e) { logger.error("", e); e.printStackTrace(); } } return font; } public void writeHeader(Document document) { Paragraph paragraphTitle = new Paragraph(pdfDocumnt.getTitle()); paragraphTitle.setFontSize(22); Paragraph paragraphBatchName = new Paragraph("(" + pdfDocumnt.getSmallTitle() + ")"); paragraphBatchName.setFontSize(12); Paragraph header = new Paragraph(); header.setTextAlignment(TextAlignment.CENTER); header.add(paragraphTitle); header.add(paragraphBatchName); document.add(header); Table table = new Table(2); table.useAllAvailableWidth(); Cell cell = new Cell(1, 1); cell.setBorder(Border.NO_BORDER); cell.setTextAlignment(TextAlignment.LEFT); cell.add(new Paragraph(pdfDocumnt.getTopLeft())); table.addCell(cell); cell = new Cell(1, 1); cell.setBorder(Border.NO_BORDER); cell.setTextAlignment(TextAlignment.RIGHT); cell.add(new Paragraph(pdfDocumnt.getTopRight())); table.addCell(cell); Border border = new SolidBorder(ColorConstants.RED, 2.0f); table.setBorderBottom(border); document.add(table); document.add(new Paragraph()); // } public void writeStaticsGrid(Document document) { //开头描述 Paragraph paragraphParent = new Paragraph(); PdfTable pdfTable = pdfDocumnt.getTable(); List<PdfTable.MyParagrah> beforeBegin = pdfTable.getBeforeBegin(); for (PdfTable.MyParagrah begin : beforeBegin) { paragraphParent.add(new Paragraph(begin.getContent()).setFontColor(begin.getColor())); } document.add(paragraphParent); //统计表格 LinkedList<PdfTable.Header> headers = pdfTable.getHeaders(); Table table = new Table(headers.size()); table.setWidth(500); for (PdfTable.Header header : headers) { table.addHeaderCell(header.getTitle()); } List<PdfTable.MyLine> lines = pdfTable.getLines(); for (PdfTable.MyLine line : lines) { for (PdfTable.Header header : headers) { table.addCell(new Paragraph(line.getCell(header.getCode()).getValue())); } } document.add(table); //空一行 document.add(new Paragraph()); //注意点描述 List<String> pations = pdfTable.getPations(); document.add(new Paragraph("注:").setFontColor(ColorConstants.RED)); for (String pation : pations) { document.add(new Paragraph(pation).setFontColor(ColorConstants.RED)); } } public void staticsDetails(Document document) { document.add(new Paragraph("报告详情").setFontSize(18)); int questionNum = 0; List<PdfDetail> details = pdfDocumnt.getDetails(); for (PdfDetail detail : details) { questionNum += 1;// addDetails(document, "问题1", " " + checkValue, 12); addDetailsNextLine(document, "问题" + questionNum, "", 15, false); Table table = new Table(1); table.useAllAvailableWidth(); List<PdfDetail.MyEntry> items = detail.getItems(); for (PdfDetail.MyEntry item : items) { if (item.getEntryType() == PdfDetail.EntryType.STRING) { addDetailsInLine(table, item.getKey(), item.getVal(), null); } else if (item.getEntryType() == PdfDetail.EntryType.IMAGE) { addDetailsInLine(table, item.getKey(), "", null); Image image = readByBase64(item.getVal()); image.setTextAlignment(TextAlignment.CENTER); image.setAutoScale(true); table.addCell(image); } } document.add(table); //这段代码注释了,这里演示的是直接给document增加图片// Image image = readByBase64(item.getVal());// image.setTextAlignment(TextAlignment.CENTER);// image.setAutoScale(true);// document.add(image);// document.add(new Paragraph(""));//增加一个空行 } } private Image readByBase64(String base64) { byte[] bytes = ImageUtil.readFromImage(base64); Image image = new Image(ImageDataFactory.create(bytes)); return image; } private void addDetailsInLine(Table table, String key, String value, Integer fontSize) { Paragraph paragraph = new Paragraph(key + ": " + value); paragraph.setMarginLeft(20); if (fontSize != null) { paragraph.setFontSize(fontSize); } Cell cell = new Cell(); cell.add(paragraph); cell.setBorder(Border.NO_BORDER); table.addCell(cell); } private void addDetailsNextLine(Document document, String key, String value, Integer fontSize, boolean useMaoHao) { String content = key + (useMaoHao ? ":" : "") + value; Paragraph paragraph = new Paragraph(content); paragraph.setMarginLeft(3); if (fontSize != null) { paragraph.setFontSize(fontSize); } document.add(paragraph); } public static File createFilePath(String path, boolean createFile) { File file = new File(path); if (!file.exists()) { if (file.isDirectory()) { file.mkdirs(); } else { File parentFile = file.getParentFile(); parentFile.mkdirs(); try { if (createFile) { file.createNewFile(); } } catch (IOException e) { e.printStackTrace(); }// return parentFile; } } return file; }} 用于携带pdf数据的实体类 MyPdfDocument

pdf数据载体

import java.util.List;public class MyPdfDocument { private String title; private String smallTitle; private String topLeft; private String topRight; private PdfTable table; private List<PdfDetail> details; public MyPdfDocument() { } public String getTitle() { return title; } public String getSmallTitle() { return smallTitle; } public void setSmallTitle(String smallTitle) { this.smallTitle = smallTitle; } public void setTitle(String title) { this.title = title; } public String getTopLeft() { return topLeft; } public void setTopLeft(String topLeft) { this.topLeft = topLeft; } public String getTopRight() { return topRight; } public void setTopRight(String topRight) { this.topRight = topRight; } public PdfTable getTable() { return table; } public void setTable(PdfTable table) { this.table = table; } public List<PdfDetail> getDetails() { return details; } public void setDetails(List<PdfDetail> details) { this.details = details; }} PdfDetail

MyPdfDocument中的detail数据载体

import java.util.LinkedList;import java.util.List;public class PdfDetail { private List<MyEntry> items = new LinkedList<>(); public PdfDetail addItem(String key, String value) { items.add(new MyEntry(key, value)); return this; } public PdfDetail addItem(String key, String value, EntryType type) { items.add(new MyEntry(key, value, type)); return this; } public List<MyEntry> getItems() { return items; } public static enum EntryType{ IMAGE, STRING } public static class MyEntry{ private EntryType entryType = EntryType.STRING; private String key; private String val; public MyEntry(String key, String val) { this.key = key; this.val = val; } public MyEntry(String key, String val, EntryType type) { this.key = key; this.val = val; this.entryType = type == null ? entryType : type; } public EntryType getEntryType() { return entryType; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public String getVal() { return val; } public void setVal(String val) { this.val = val; } }} PdfTable

MyPdfDocument中的table数据载体

import com.itextpdf.kernel.colors.Color;import java.util.HashMap;import java.util.LinkedList;import java.util.List;import java.util.Map;public class PdfTable { private List<MyParagrah> beforeBegin; private LinkedList<Header> headers; private List<MyLine> lines; private List<String> pations; public static class MyParagrah { private String content; private Color color;//ColorConstants.BLACK public MyParagrah(String content, Color color) { this.content = content; this.color = color; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public Color getColor() { return color; } public void setColor(Color color) { this.color = color; } } public static class MyCell { private int headerCode; private String value; public MyCell(int headerCode, String value) { this.headerCode = headerCode; this.value = value; } public int getHeaderCode() { return headerCode; } public void setHeaderCode(int headerCode) { this.headerCode = headerCode; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } } public static class MyLine { private Map<Integer, MyCell> cells = new HashMap<>(); public MyLine addCell(MyCell cell) { cells.put(cell.getHeaderCode(), cell); return this; } public Map<Integer, MyCell> getCells() { return cells; } public MyCell getCell(int headerCode) { return cells.get(headerCode); } } public static class Header { private int code; private String title; public Header(int code, String title) { this.code = code; this.title = title; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } } public List<MyParagrah> getBeforeBegin() { return beforeBegin; } public void setBeforeBegin(List<MyParagrah> beforeBegin) { this.beforeBegin = beforeBegin; } public LinkedList<Header> getHeaders() { return headers; } public void setHeaders(LinkedList<Header> headers) { this.headers = headers; } public List<MyLine> getLines() { return lines; } public void setLines(List<MyLine> lines) { this.lines = lines; } public List<String> getPations() { return pations; } public void setPations(List<String> pations) { this.pations = pations; }}

测试类 @Test public void testHelper() { MyPdfDocument myPdfDocument = new MyPdfDocument(); myPdfDocument.setTitle("jfqqqqq的监测报告"); myPdfDocument.setSmallTitle("他很帅"); myPdfDocument.setTopLeft("jfqqqq的个人管理平台"); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); myPdfDocument.setTopRight(simpleDateFormat.format(new Date())); PdfTable pdfTable = new PdfTable(); List<PdfTable.MyParagrah> beforeBegins = new LinkedList<>() {{ add(new PdfTable.MyParagrah("说点什么好呢,总的来说,这次的监测效果还算不错,我很努力,", ColorConstants.BLACK)); add(new PdfTable.MyParagrah("值得嘉奖一下kkkkkkkkkkk值得嘉奖一下kkkkkkkkkkk值得嘉奖一下kkkkkkkkkkk值得嘉奖一下kkkkkkkkkkk值得嘉奖一下kkkkkkkkkkk", ColorConstants.RED)); add(new PdfTable.MyParagrah("。嘉奖一下我自己!", ColorConstants.BLACK)); }}; pdfTable.setBeforeBegin(beforeBegins); LinkedList<PdfTable.Header> headers = new LinkedList<>() {{ add(new PdfTable.Header(1, "序号")); add(new PdfTable.Header(2, "项目")); add(new PdfTable.Header(3, "努力")); add(new PdfTable.Header(4, "视力")); }}; pdfTable.setHeaders(headers); List<PdfTable.MyLine> lines = new LinkedList<>(); for (int i = 0; i < 5; i++) { PdfTable.MyLine line = new PdfTable.MyLine(); line.addCell(new PdfTable.MyCell(1, "1")).addCell(new PdfTable.MyCell(2, "身高" + i)).addCell(new PdfTable.MyCell(3, "很努力,还行吧" + i)).addCell(new PdfTable.MyCell(4, "哈哈" + i)); lines.add(line); } pdfTable.setLines(lines); pdfTable.setPations(new LinkedList<String>() {{ add("1、这里是注释1"); add("2、这里是注释2"); }}); myPdfDocument.setTable(pdfTable); List<PdfDetail> details = new ArrayList<>(); for (int i = 0; i < 5; i++) { PdfDetail pdfDetail = new PdfDetail(); String base64Image = "data:image/gif;base64,R0lGODlhDwAPAKECAAAAzMzM/wAAACwAAAAADwAPAAACIISPeQHsrZ5ModrLlN48CXF8m2iQ3YmmKqVlRtW4MLwWACH+H09wdGltaXplZCBieSBVbGVhZCBTbWFydFNhdmVyIQAAOw=="; pdfDetail.addItem("身高", "身高" + i).addItem("努力", "很努力,还行吧" + i).addItem("视力", "哈哈" + i).addItem("截图", base64Image, PdfDetail.EntryType.IMAGE); details.add(pdfDetail); } myPdfDocument.setDetails(details); PdfUtil_v2 pdf = new PdfUtil_v2(myPdfDocument, "I:\\tobedelete\\asd.pdf", "F:\\anytest\\pdf\\src\\main\\resources\\fonts\\SimSun-01.ttf"); pdf.generate(); System.out.println("success!"); } 字体文件

想要打印中文需要有中文字体支持的字体文件。可以到C:\Windows\Fonts中找一个中文字体文件给程序使用,或者自己从网上下载。

效果

附加

返回pdf文件时,响应头一般用这两种:

1. content-type:application/pdf 使用比如:

response.setContentType("application/pdf");

2. Content-Disposition:attachment; filename=aa.pdf

使用比如:response.setHeader("Content-Disposition", "attachment; filename=" + new String((batchName + ".pdf").getBytes(), "utf-8"));

标签:
声明:无特别说明,转载请标明本文来源!
发布评论
正文 取消