Java生成PDF文件(Itext篇)

版权声明:Soulmate_Min专属 https://blog.csdn.net/Soulmate_Min/article/details/81707918

在企业的信息系统中,报表处理一直占比较重要的作用,iText是一种生成PDF报表的Java组件。通过在服务器端使用Jsp或JavaBean生成PDF报表,客户端采用超链接显示或下载得到生成的报表,这样就很好的解决了B/S系统的报表处理问题。

iText简介

iText是著名的开放源码的站点sourceforge一个项目,是用于生成PDF文档的一个java类库。通过iText不仅可以生成PDF或rtf的文档,而且可以将XML、Html文件转化为PDF文件。 iText的安装非常方便,下载iText.jar文件后,只需要在系统的CLASSPATH中加入iText.jar的路径,在程序中就可以使用iText类库了。

一、关于Itext的安装

IText的安装非常方便,在http://itextpdf.com/ 网站上下载iText.jar文件后,只需要在系统的CLASSPATH中加入iText.jar的路径,在程序中就可以使用iText类库了。本次示例所使用的jar包有三个。

下载地址:https://pan.baidu.com/s/1VO4J74BK5m7eRLf73KN-4Q

二、项目搭建。

本示例使用SSM架构,具体项目搭建流程请访问博客查看:https://blog.csdn.net/Soulmate_Min

三、构建代码

首先,将下载好的jar包导入项目,将jar包Build Path。

1.写测试类:本示例创建class名为GetReportController

2.添加两张图片,一张为LOGO,一张为水印图片。作为备用。

3.测试类代码展示:

       代码如下:

package com.gcx.test.controller;

import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.gcx.test.util.NewCreditReportUtil;

@Controller
@RequestMapping("/CreditReporterController")

public class GetReportController {
	
	@RequestMapping("/getreport")
	@ResponseBody
	public String getreport(String corpname,HttpServletRequest request) throws Exception{
		//报告准备工作
		
		//生成的PDF报告编号
		String reportNo = "GCX-2"+System.currentTimeMillis();
		//PDF文件名称
		String pdfFileName = reportNo + ".pdf";
		//水印图片地址
		String watermarkFilePath = request.getSession().getServletContext().getRealPath("/images/watermark.png");
		//公司LOGO地址
		String reportLogoFilePath = request.getSession().getServletContext().getRealPath("/images/credit_report_logo.png");
		
		//定义一个Map,将生成的PDF需要的参数填入Map, Map将作为参数传到PDF模板中。
		Map<String, Object> NewCorpReportMap=new  HashMap<>();
		NewCorpReportMap.put("reportLogoFilePath", reportLogoFilePath);
		NewCorpReportMap.put("reportNo", reportNo);
		NewCorpReportMap.put("watermarkFilePath", watermarkFilePath);
		NewCorpReportMap.put("corpname", corpname);
		
		//调取PDF工具类中的方法,将Map参数传入。
		NewCreditReportUtil.generateDeepthCreditReport(NewCorpReportMap);
		String s1 = "C://Users//sungm//Desktop//Test" + pdfFileName;
		//给文件加水印
		NewCreditReportUtil.addPdfMark("C:/Users/sungm/Desktop/Test/GCX-creditreport-template.pdf", s1, NewCorpReportMap.get("watermarkFilePath").toString());
		return reportNo;
	}
}

4.生成PDF所需工具类展示:

/**
 * 用iText生成PDF文档需要5个步骤:
 * 
 * ①建立com.lowagie.text.Document对象的实例。
 * Document document = new Document(); 
 * 
 * ②建立一个书写器(Writer)与document对象关联,通过书写器(Writer)可以将文档写入到磁盘中。
 * PDFWriter.getInstance(document, new FileOutputStream("Helloworld.PDF")); 
 * 
 * ③打开文档。
 * document.open(); 
 * 
 * ④向文档中添加内容。
 * document.add(new Paragraph("Hello World")); 
 * 
 * ⑤关闭文档。
 * document.close(); 
 *
 */

添加水印方法:

paragraph格式:

居中无边框的cell:

不居中无边框的cell:

居中有边框的cell:

居中有边框的cell:

对doc文件添加页眉页脚方法:

设置字体:

插入图片:

首页--固定格式布局:本示例固定的格式,具体样式可以根据需求自己修改

非空判断:

完整工具类代码(包含以上所有示例):

package com.gcx.test.util;

import java.awt.Color;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.HeaderFooter;
import com.lowagie.text.Image;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Phrase;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfStamper;
import com.lowagie.text.pdf.PdfWriter;

/**
 * 用iText生成PDF文档需要5个步骤:
 * 
 * ①建立com.lowagie.text.Document对象的实例。
 * Document document = new Document(); 
 * 
 * ②建立一个书写器(Writer)与document对象关联,通过书写器(Writer)可以将文档写入到磁盘中。
 * PDFWriter.getInstance(document, new FileOutputStream("Helloworld.PDF")); 
 * 
 * ③打开文档。
 * document.open(); 
 * 
 * ④向文档中添加内容。
 * document.add(new Paragraph("Hello World")); 
 * 
 * ⑤关闭文档。
 * document.close(); 
 *
 */
public class NewCreditReportUtil {
	//定义静态变量,用于生成水印文件名称
	private final static String RESULT_FILE = "C:/Users/sungm/Desktop/Test/GCX-creditreport-template.pdf";
	
	public static boolean generateDeepthCreditReport(Map<String, Object> NewCorpReportMap)
			throws MalformedURLException, IOException, DocumentException {
		
		//①建立com.lowagie.text.Document对象的实例。
		Document doc = new Document();
		doc.setMargins(20, 20, 30, 30);
		String fontPath = "C:/Users/sungm/Desktop/Test";
		
		//②建立一个书写器(Writer)与document对象关联,通过书写器(Writer)可以将文档写入到磁盘中。
		PdfWriter.getInstance(doc, new FileOutputStream(RESULT_FILE));
		
		// 设置中文字体
		BaseFont fontChinese = BaseFont.createFont(fontPath + "/simfang.ttf", BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
		Font chinese = new Font(fontChinese, 10, Font.NORMAL);
		
		// 添加页眉页脚
		String headertitle = "*****报告" + "         " + "*******";
		addheaderandfooter(doc, chinese, headertitle);
		
		//③打开文档。
		doc.open();
		
		// 18.0F是字体大小,0表示字体倾斜度, font.setStyle(1); 0:无变化1:加粗;2:斜体...
		// font.setFamily("微软雅黑"); // 设置字体
		Font myfont  = setfont(fontPath + "/msyh.ttf", 13.0F, 0, Color.BLACK, 0);// 基本字体
		//Font myfont1 = setfont(fontPath + "/msyh.ttf", 36.0F, 0, Color.BLACK, 1);// 标头字体(一级字体)
		//Font myfont2 = setfont(fontPath + "/msyh.ttf", 27.0F, 0, Color.BLACK, 1);// 标头字体(二级字体)
		Font myfont3 = setfont(fontPath + "/msyh.ttf", 18.0F, 0, Color.BLACK, 1);// 标头字体(三级字体)
		//Font myfont4 = setfont(fontPath + "/msyh.ttf", 13.0F, 0, Color.BLACK, 1);// 标头字体(四级字体)
		//Font myfont5 = setfont(fontPath + "/msyh.ttf", 12.0F, 0, Color.BLACK, 0);// 标头字体(五级字体)
		
		// 初始化pdf基本功能性文本
		Image image = null;
		PdfPTable table;
		PdfPCell cell = null;
		Paragraph paragraph = null;
		
		// 准备工作结束,进行文档内容填充:
		// 添加公司logo图片
		table = new PdfPTable(1);
		String picpath = NewCorpReportMap.get("reportLogoFilePath").toString();
		addpicture(table, image, picpath, cell, doc);
		
		// 添加报告信息
		firstpage(cell, table, paragraph, NewCorpReportMap.get("corpname").toString(), "企业信用报告",
				NewCorpReportMap.get("reportNo").toString(), myfont, myfont3, doc);
		
		// 第二页 (固定死页面)
		doc.newPage();
		doc.add(new Paragraph("       ", myfont));
		paragraph = new Paragraph("报告说明", myfont3);
		paragraph.setAlignment(1);
		doc.add(paragraph);
		doc.add(new Paragraph("       ", myfont));

		geshi1(new Paragraph("1. 内容1",myfont), doc);
		geshi1(new Paragraph("2. 内容2", myfont), doc);
		geshi1(new Paragraph("3. 内容3", myfont), doc);
		geshi1(new Paragraph("4. 内容4", myfont), doc);

		// 第三页 报告摘要,每页空2行留给页眉
		doc.newPage();
		doc.add(new Paragraph("       ", myfont));
		doc.add(new Paragraph("       ", myfont));

		doc.close();
		return false;
	}

	/**
	 * 给pdf文件添加水印
	 * 
	 * @param InPdfFile
	 *            要加水印的原pdf文件路径
	 * @param outPdfFile
	 *            加了水印后要输出的路径
	 * @param object
	 *            水印图片路径
	 * @param pageSize
	 *            原pdf文件的总页数(该方法是我当初将数据导入excel中然后再转换成pdf所以我这里的值是用excel的行数计算出来的,
	 *            如果不是我这种可以 直接用reader.getNumberOfPages()获取pdf的总页数)
	 * @throws Exception
	 */
	public static void addPdfMark(String InPdfFile, String outPdfFile, String readpicturepath) throws Exception {
		PdfReader reader = new PdfReader(InPdfFile);
		int pageSize = reader.getNumberOfPages();
		PdfStamper stamp = new PdfStamper(reader, new FileOutputStream(outPdfFile));
		Image img = Image.getInstance(readpicturepath);// 插入水印
		img.setAbsolutePosition(0, 0);
		for (int i = 1; i <= pageSize; i++) {
			PdfContentByte under = stamp.getUnderContent(i);
			under.addImage(img);
		}
		stamp.close();// 关闭
		File tempfile = new File(InPdfFile);
		if (tempfile.exists()) {
			tempfile.delete();
		}
	}

	// paragraph的格式
	public static void geshi1(Paragraph paragraph, Document doc) throws DocumentException {// 段落的格式
		paragraph.setIndentationLeft(30);
		paragraph.setIndentationRight(30);
		paragraph.setFirstLineIndent(20f);
		paragraph.setSpacingAfter(10f);
		paragraph.setSpacingBefore(10f);
		doc.add(paragraph);
	}

	// 居中无边框的cell
	public static void geshi2(PdfPCell cell, PdfPTable table) throws DocumentException {// 表格的格式
		cell.setBorder(PdfPCell.NO_BORDER);
		cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
		cell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);
		cell.setVerticalAlignment(PdfPCell.ALIGN_CENTER);
		table.addCell(cell);
	}

	// 不居中无边框的cell
	public static void geshi12(PdfPCell cell, PdfPTable table) throws DocumentException {// 表格的格式
		cell.setBorder(PdfPCell.NO_BORDER);
		table.addCell(cell);
	}

	// 居中有边框的cell
	public static void geshi22(PdfPCell cell, PdfPTable table) throws DocumentException {// 表格的格式
		cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
		cell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);
		cell.setVerticalAlignment(PdfPCell.ALIGN_CENTER);
		table.addCell(cell);
	}

	// 居中有边框的cell
	public static void geshi32(PdfPCell cell, PdfPTable table) throws DocumentException {// 表格的格式
		cell.setColspan(3);
		cell.setBorder(0);
		table.addCell(cell);
	}

	// 对doc文件添加页眉页脚方法
	public static void addheaderandfooter(Document doc, Font chinese, String headertitle) {
		// 设置页眉页脚方法
		/**
		 * HeaderFooter的第2个参数为非false时代表打印页码 页眉页脚中也可以加入图片,并非只能是文字
		 */

		HeaderFooter header = new HeaderFooter(new Phrase(headertitle, chinese), false);
		header.setBorder(Rectangle.NO_BORDER);
		header.setBorder(Rectangle.BOTTOM);
		header.setAlignment(1);
		header.setBorderColor(Color.red);
		doc.setHeader(header);

		HeaderFooter footer = new HeaderFooter(new Phrase("第-", chinese), new Phrase("-页", chinese));
		/**
		 * 0是靠左 1是居中 2是居右
		 */
		footer.setAlignment(1);
		footer.setBorderColor(Color.red);
		footer.setBorder(Rectangle.NO_BORDER);
		doc.setFooter(footer);

		/**
		 * 页眉页脚的设置一定要在open前设置好
		 */
	}

	// 设置字体
	public static Font setfont(String fonttype, float fontsize, int fontflag, Color fontcolor, int fontstyle)
			throws DocumentException, IOException {
		BaseFont baseFont5 = BaseFont.createFont(fonttype, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
		Font font = new Font(baseFont5, fontsize, fontflag);
		font.setColor(fontcolor);
		if (fontstyle != 0) {// 如果传参为0不设置字体
			font.setStyle(fontstyle);
		}
		return font;
	}

	// 插入图片
	public static void addpicture(PdfPTable table, Image image, String picpath, PdfPCell cell, Document doc)
			throws MalformedURLException, IOException, DocumentException {
		image = Image.getInstance(picpath);
		cell = new PdfPCell(image);
		geshi2(cell, table);
		doc.add(table);
	}

	// 首页--固定格式布局
	public static void firstpage(PdfPCell cell, PdfPTable table, Paragraph paragraph, String corpname,
			String reporttype, String reportNo, Font myfont, Font myfont3, Document doc) throws DocumentException {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
		String newyear = sdf.format(new Date());

		paragraph = new Paragraph(corpname + newyear, myfont3);// 公司名
		paragraph.setAlignment(1);
		doc.add(paragraph);

		paragraph = new Paragraph("企业信用报告", myfont3);// 信用报告类型
		paragraph.setAlignment(1);
		doc.add(paragraph);

		doc.add(new Paragraph("       ", myfont));
		doc.add(new Paragraph("       ", myfont));
		doc.add(new Paragraph("       ", myfont));
		doc.add(new Paragraph("       ", myfont));
		doc.add(new Paragraph("       ", myfont));
		doc.add(new Paragraph("       ", myfont));

		table = new PdfPTable(2);
		cell = new PdfPCell(new Phrase("报告编号:" + reportNo, myfont));
		cell.setBorder(PdfPCell.NO_BORDER);// Rectangle.NO_BORDER
		table.addCell(cell);
		cell = new PdfPCell(new Phrase("报告生成时间:" + sdf.format(new Date()), myfont));
		cell.setBorder(PdfPCell.NO_BORDER);// Rectangle.NO_BORDER
		table.addCell(cell);

		cell = new PdfPCell(new Phrase("报告生成机构:*****有限公司", myfont));
		cell.setBorder(PdfPCell.NO_BORDER);// Rectangle.NO_BORDER
		table.addCell(cell);

		cell = new PdfPCell(new Phrase("报告结论机构:******研究院", myfont));
		cell.setBorder(PdfPCell.NO_BORDER);// Rectangle.NO_BORDER
		table.addCell(cell);

		doc.add(table);
	}
	//非空判断
	public static String isnull(Object a) {
		if (a != null && a != "" && a != "null" && a.toString() != "null") {
			return a.toString();
		} else {
			return "";
		}
	}
}

完成后,启动项目测试功能是否存在问题:

打开浏览器,在地址栏中访问接口:

http://localhost:8080/test/CreditReporterController/getreport.do?corpname=*****有限公司

访问成功后,返回文件路径:

文件自动下载到桌面:

打开PDF文件,查看格式是否正确:

成功生成PDF文件。

接口测试成功。

猜你喜欢

转载自blog.csdn.net/Soulmate_Min/article/details/81707918