Springboot输出PDF文件

  • 2019 年 10 月 8 日
  • 笔记

前言

有个人(死需求)跑过来跟你说,这些都给我输出成报告,pdf格式的,所以就有了下面这个,做一下笔记,以后有用直接过来拿。在网上找了一下,发现大家都是在用itext。iText是著名的开放项目,是用于生成PDF文档的一个java类库。通过iText不仅可以生成PDF或rtf的文档,而且可以将XML、Html文件转化为PDF文件。

http://itextpdf.com/

maven依赖

<dependency>              <groupId>com.itextpdf</groupId>              <artifactId>itextpdf</artifactId>              <version>5.5.10</version>          </dependency>            <dependency>              <groupId>com.itextpdf</groupId>              <artifactId>itext-asian</artifactId>              <version>5.2.0</version>          </dependency>

基础操作

itext有很多功能,这里先说基本的操作。其他更多高级的操作,可以继续看下面的。基本处理步骤如下伪代码:

//Step 1—Create a Document.  Document document = new Document();  //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();

1、直接输出数据到pdf文件

这里有个特别注意的是,中文必须要指定字体,即是BaseFont

public class PDFReport {        private final static String REPORT_PATH = "C:/air-navi-monitor/report";        private static void exportReport() {          BaseFont bf;          Font font = null;          Font font2 = null;          try {                bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H",                      BaseFont.NOT_EMBEDDED);//创建字体              font = new Font(bf, 12);//使用字体              font2 = new Font(bf, 12, Font.BOLD);//使用字体          } catch (Exception e) {              e.printStackTrace();          }          Document document = new Document();          try {              PdfWriter.getInstance(document, new FileOutputStream("E:/2.pdf"));              document.open();              Paragraph elements = new Paragraph("常州武进1区飞行报告", font2);              elements.setAlignment(Paragraph.ALIGN_CENTER);              document.add(elements);              Image png = Image.getInstance("E:\test.png");              png.setAlignment(Image.ALIGN_CENTER);              document.add(png);              document.add(new Paragraph("任务编号:20190701        开始日期:20190701", font));              document.add(new Paragraph("任务名称:常州武进1区     结束日期:20190701", font));              document.add(new Paragraph("平均飞行高度:100m        平均飞行速度:100km/h", font));              document.add(new Paragraph("任务面积:1000㎡      结束日期:20190701", font));              document.add(new Paragraph("飞行总时长:1000㎡", font));              document.addCreationDate();                document.close();          } catch (Exception e) {              System.out.println("file create exception");          }      }        /**       * 生成pdf文件       *       * @param missionReport       * @return       */      public static String exportReport(MissionReportTb missionReport) throws AirNaviException {          String pdfPath = null;          String imgPath = Shape2Image.getImgPath(missionReport.getMissionID());  //        String imgPath = "E:\test.png";          String finalReportStr = missionReport.getMissionReport();          MissionReport finalReport = JSONObject.parseObject(finalReportStr, MissionReport.class);          BaseFont bf;          Font font = null;          Font font2 = null;          try {              bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H",                      BaseFont.NOT_EMBEDDED);//创建字体              font = new Font(bf, 12);//使用字体              font2 = new Font(bf, 12, Font.BOLD);//使用字体          } catch (Exception e) {              e.printStackTrace();          }          Document document = new Document();          try {              File dir = new File(REPORT_PATH);              if (!dir.exists()) {                  dir.mkdirs();              }              File file = new File(REPORT_PATH + File.separator + missionReport.getMissionID() + ".pdf");              if (!file.exists()) {                  file.createNewFile();              }              PdfWriter.getInstance(document, new FileOutputStream(REPORT_PATH + File.separator + missionReport.getMissionID() + ".pdf"));              document.open();              Paragraph elements = new Paragraph(missionReport.getMissionName() + "飞行报告", font2);              elements.setAlignment(Paragraph.ALIGN_CENTER);              document.add(elements);              Image png = Image.getInstance(imgPath);  //            https://blog.csdn.net/lingbo89/article/details/76177825              float documentWidth = document.getPageSize().getWidth() - document.leftMargin() - document.rightMargin();              float documentHeight = documentWidth / 580 * 320;//重新设置宽高              png.scaleAbsolute(documentWidth, documentHeight);//重新设置宽高              png.scalePercent(50);              // 根据域的大小缩放图片  //            image.scaleToFit(signRect.getWidth(), signRect.getHeight());              png.setAlignment(Image.ALIGN_CENTER);              document.add(png);              document.add(new Paragraph("任务编号:" + missionReport.getMissionCode() + ",开始日期:" + finalReport.getStartTime(), font));              document.add(new Paragraph("任务名称:" + missionReport.getMissionName() + ",结束日期:" + finalReport.getEndTime(), font));              document.add(new Paragraph("平均飞行高度:" + finalReport.getAvgFlightHeight() + "m" + ",平均飞行速度:" + finalReport.getAvgFlightSpeed() + "km/h", font));              document.add(new Paragraph("任务面积:" + finalReport.getMissionArea() + "㎡" + ",飞行总时长:" + finalReport.getFlightDuration() + "min", font));              document.addCreationDate();              document.close();              pdfPath = file.getAbsolutePath();          } catch (Exception e) {              e.printStackTrace();              log.error(e.getMessage());              System.out.println("file create exception");              throw new AirNaviException("生成PDF失败:" + e.getMessage());          }            return pdfPath;      }        public static void main(String[] args) throws AirNaviException {          String report = "{"detailMissionReport":[{"avgFlightHeight":119.7,"avgFlightSpeed":71.1,"endPoint":"113.27484,22.86843","endTime":"2019-09-17 17:47:07","flightDuration":9,"reportID":1,"startPoint":"113.31429,22.78240","startTime":"2019-09-17 17:38:03","statisticsTimes":505}],"missionReport":{"avgFlightHeight":119.7,"avgFlightSpeed":71.1,"endPoint":"113.31429,22.78240","endTime":"2019-09-17 17:47:07","flightDuration":9,"reportID":1,"startPoint":"113.31429,22.78240","startTime":"2019-09-17 17:38:03","statisticsTimes":0},"missionArea":0.0,"missionCode":"M001","missionID":"888813ddef6646cd9bfaba5abb748a43","missionName":"德胜航点M008","missionStatus":1,"missionType":0,"plannedFlightTime":"20190909"}";          MissionReportTb missionReportTb = JSONObject.parseObject(report, MissionReportTb.class);          exportReport(missionReportTb);      }    }

2、根据模板生成pdf文件并导出

首先你的制作一个pdf模板:

1.先用word做出模板界面

2.文件另存为pdf格式文件

3.通过Adobe Acrobat pro软件打开刚刚用word转换成的pdf文件(注:如果没有这个软件可以通过我的百度云下载,链接:http://pan.baidu.com/s/1pL2klzt)如果无法下载可以Google一下。

4.点击右边的"准备表单"按钮,选择"测试.pdf"选择开始

进去到编辑页面,打开后它会自动侦测并命名表单域,右键表单域,点击属性,出现文本域属性对话框(其实无需任何操作,一般情况下不需要修改什么东西,至少我没有修改哦。如果你想修改fill1等信息,可以进行修改)

5.做完上面的工作后,直接"另存为"将pdf存储就可以

以上部分是制作pdf模板操作,上述完成后,就开始通过程序来根据pdf模板生成pdf文件了,上java程序:

public class Snippet {  // 利用模板生成pdf      public static void fillTemplate() {  // 模板路径          String templatePath = "E:/测试3.pdf";  // 生成的新文件路径          String newPDFPath = "E:/ceshi.pdf";          PdfReader reader;          FileOutputStream out;          ByteArrayOutputStream bos;          PdfStamper stamper;          try {              out = new FileOutputStream(newPDFPath);// 输出流              reader = new PdfReader(templatePath);// 读取pdf模板              bos = new ByteArrayOutputStream();              stamper = new PdfStamper(reader, bos);              AcroFields form = stamper.getAcroFields();              String[] str = {"123456789", "TOP__ONE", "男", "1991-01-01", "130222111133338888", "河北省保定市"};              int i = 0;              java.util.Iterator<String> it = form.getFields().keySet().iterator();              while (it.hasNext()) {                  String name = it.next().toString();                  System.out.println(name);                  form.setField(name, str[i++]);              }              stamper.setFormFlattening(true);// 如果为false那么生成的PDF文件还能编辑,一定要设为true              stamper.close();              Document doc = new Document();              PdfCopy copy = new PdfCopy(doc, out);              doc.open();              PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);              copy.addPage(importPage);              doc.close();          } catch (IOException e) {              System.out.println(1);          } catch (DocumentException e) {              System.out.println(2);          }      }        public static void main(String[] args) {          fillTemplate();      }  }

运行结果如下

更多操作

1、页面大小,页面背景色,页边空白,Title,Author,Subject,Keywords

//页面大小  Rectangle rect = new Rectangle(PageSize.B5.rotate());  //页面背景色  rect.setBackgroundColor(BaseColor.ORANGE);    Document doc = new Document(rect);    PdfWriter writer = PdfWriter.getInstance(doc, out);    //PDF版本(默认1.4)  writer.setPdfVersion(PdfWriter.PDF_VERSION_1_2);    //文档属性  doc.addTitle("Title@sample");  doc.addAuthor("Author@rensanning");  doc.addSubject("Subject@iText sample");  doc.addKeywords("Keywords@iText");  doc.addCreator("Creator@iText");    //页边空白  doc.setMargins(10, 20, 30, 40);    doc.open();  doc.add(new Paragraph("Hello World"));

输出结果:

2、设置密码

PdfWriter writer = PdfWriter.getInstance(doc, out);    // 设置密码为:"World"  writer.setEncryption("Hello".getBytes(), "World".getBytes(),          PdfWriter.ALLOW_SCREENREADERS,          PdfWriter.STANDARD_ENCRYPTION_128);    doc.open();  doc.add(new Paragraph("Hello World"));

输出结果:

3、添加Page

document.open();  document.add(new Paragraph("First page"));  document.add(new Paragraph(Document.getVersion()));    document.newPage();  writer.setPageEmpty(false);    document.newPage();  document.add(new Paragraph("New page"));

4、添加水印(背景图)

//图片水印  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();

5、插入Chunk, Phrase, Paragraph, List

//Chunk对象: a String, a Font, and some attributes  document.add(new Chunk("China"));  document.add(new Chunk(" "));  Font font = new Font(Font.FontFamily.HELVETICA, 6, Font.BOLD, BaseColor.WHITE);  Chunk id = new Chunk("chinese", font);  id.setBackground(BaseColor.BLACK, 1f, 0.5f, 1f, 1.5f);  id.setTextRise(6);  document.add(id);  document.add(Chunk.NEWLINE);    document.add(new Chunk("Japan"));  document.add(new Chunk(" "));  Font font2 = new Font(Font.FontFamily.HELVETICA, 6, Font.BOLD, BaseColor.WHITE);  Chunk id2 = new Chunk("japanese", font2);  id2.setBackground(BaseColor.BLACK, 1f, 0.5f, 1f, 1.5f);  id2.setTextRise(6);  id2.setUnderline(0.2f, -2f);  document.add(id2);  document.add(Chunk.NEWLINE);    //Phrase对象: a List of Chunks with leading  document.newPage();  document.add(new Phrase("Phrase page"));    Phrase director = new Phrase();  Chunk name = new Chunk("China");  name.setUnderline(0.2f, -2f);  director.add(name);  director.add(new Chunk(","));  director.add(new Chunk(" "));  director.add(new Chunk("chinese"));  director.setLeading(24);  document.add(director);    Phrase director2 = new Phrase();  Chunk name2 = new Chunk("Japan");  name2.setUnderline(0.2f, -2f);  director2.add(name2);  director2.add(new Chunk(","));  director2.add(new Chunk(" "));  director2.add(new Chunk("japanese"));  director2.setLeading(24);  document.add(director2);    //Paragraph对象: a Phrase with extra properties and a newline  document.newPage();  document.add(new Paragraph("Paragraph page"));    Paragraph info = new Paragraph();  info.add(new Chunk("China "));  info.add(new Chunk("chinese"));  info.add(Chunk.NEWLINE);  info.add(new Phrase("Japan "));  info.add(new Phrase("japanese"));  document.add(info);    //List对象: a sequence of Paragraphs called ListItem  document.newPage();  List list = new List(List.ORDERED);  for (int i = 0; i < 10; i++) {      ListItem item = new ListItem(String.format("%s: %d movies",              "country" + (i + 1), (i + 1) * 100), new Font(              Font.FontFamily.HELVETICA, 6, Font.BOLD, BaseColor.WHITE));      List movielist = new List(List.ORDERED, List.ALPHABETICAL);      movielist.setLowercase(List.LOWERCASE);      for (int j = 0; j < 5; j++) {          ListItem movieitem = new ListItem("Title" + (j + 1));          List directorlist = new List(List.UNORDERED);          for (int k = 0; k < 3; k++) {              directorlist.add(String.format("%s, %s", "Name1" + (k + 1),                      "Name2" + (k + 1)));          }          movieitem.add(directorlist);          movielist.add(movieitem);      }      item.add(movielist);      list.add(item);  }  document.add(list);

6、插入表格

PdfPTable table = new PdfPTable(3);  PdfPCell cell;  cell = new PdfPCell(new Phrase("Cell with colspan 3"));  cell.setColspan(3);  table.addCell(cell);  cell = new PdfPCell(new Phrase("Cell with rowspan 2"));  cell.setRowspan(2);  table.addCell(cell);  table.addCell("row 1; cell 1");  table.addCell("row 1; cell 2");  table.addCell("row 2; cell 1");  table.addCell("row 2; cell 2");    document.add(table);

7、表格嵌套

PdfPTable table = new PdfPTable(4);    //1行2列  PdfPTable nested1 = new PdfPTable(2);  nested1.addCell("1.1");  nested1.addCell("1.2");    //2行1列  PdfPTable nested2 = new PdfPTable(1);  nested2.addCell("2.1");  nested2.addCell("2.2");    //将表格插入到指定位置  for (int k = 0; k < 24; ++k) {      if (k == 1) {          table.addCell(nested1);      } else if (k == 20) {          table.addCell(nested2);      } else {          table.addCell("cell " + k);      }  }    document.add(table);

8、设置表头

String[] bogusData = { "M0065920", "SL", "FR86000P", "PCGOLD",          "119000", "96 06", "2001-08-13", "4350", "6011648299",          "FLFLMTGP", "153", "119000.00" };  int NumColumns = 12;  // 12  PdfPTable datatable = new PdfPTable(NumColumns);  int headerwidths[] = { 9, 4, 8, 10, 8, 11, 9, 7, 9, 10, 4, 10 }; // percentage  datatable.setWidths(headerwidths);  datatable.setWidthPercentage(100);  datatable.getDefaultCell().setPadding(3);  datatable.getDefaultCell().setBorderWidth(2);  datatable.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER);    datatable.addCell("Clock #");  datatable.addCell("Trans Type");  datatable.addCell("Cusip");  datatable.addCell("Long Name");  datatable.addCell("Quantity");  datatable.addCell("Fraction Price");  datatable.addCell("Settle Date");  datatable.addCell("Portfolio");  datatable.addCell("ADP Number");  datatable.addCell("Account ID");  datatable.addCell("Reg Rep ID");  datatable.addCell("Amt To Go ");    datatable.setHeaderRows(1);    //边框  datatable.getDefaultCell().setBorderWidth(1);    //背景色  for (int i = 1; i < 1000; i++) {      for (int x = 0; x < NumColumns; x++) {          datatable.addCell(bogusData[x]);      }  }    document.add(datatable);

篇幅有限,如果你需要更多操作,可以参考文章:

https://www.cnblogs.com/liaojie970/p/7132475.html