iText是一种生成PDF报表的Java组件。通过在服务器端使用Jsp或JavaBean生成PDF报表,客户端采用超链接显示或下载得到生成的报表,这样就很好的解决了B/S系统的报表处理问题。在使用iText的过程中,遇到了一下几个问题。
1.中文不显示
2.没有合适的工具类样式
3.用输出流导出可供浏览器下载的问题
几经度娘最终整合了很多代码,终于汇总成了可以简易使用的工具类
1.中文不显示
主要是itext版本的问题,itext一开始是只有一个itext的jar包,后来升级后拆分成两个jar包,一个是itextpdf一个是itext-asian。我这边使用的版本是itextpdf-5.5.6.jar和itext-asian-5.2.0.jar。确保itext版本匹配。itext-asian中含有中文字体包,可以直接使用这里的中文字体。当然也推荐这种方式,因为其他方式依赖于环境的字体包。
//1:使用iTextAsian.jar包中的字体 BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); Font font = new Font(baseFont); //2:使用Windows系统字体 BaseFont baseFont_zh = BaseFont.createFont("C:\\Windows\\Fonts\\simsunb.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); Font font_zh = new Font(baseFont_zh); //3:使用资源字体,也就是自己下载的字体 BaseFont baseFont_resources = BaseFont.createFont("\\font\\方正舒体.TIF",BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED); Font font_resources = new Font(baseFont_resources)
2.iText工具类
使用工具类可以快速生成表格、段落、标题、分页,并且对这些元素进行基本的设置。
import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.List; import com.itextpdf.text.BaseColor; import com.itextpdf.text.Element; import com.itextpdf.text.Font; import com.itextpdf.text.Paragraph; import com.itextpdf.text.pdf.BaseFont; import com.itextpdf.text.pdf.PdfPCell; import com.itextpdf.text.pdf.PdfPTable; public class PDFUtil { static BaseFont baseFont = null; static { try { baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } /** * PDF大标题字体 */ public static Font PDFTITLEFONT = new Font(baseFont, 16, Font.BOLD); /** * PDF小标题字体 */ public static Font PDFTITLEFONT1 = new Font(baseFont, 13, Font.NORMAL); /** * 表格宽度百分比 */ public static Integer WIDTHPERCENTAGE = 98; /** * 表格标题字体 */ public static Font TITLEFONT = new Font(baseFont, 12, Font.NORMAL); /** * 翻页加载表头 */ public static Integer HEADERROWS = 1; /** * 翻页不加载表头 */ public static Integer NOHEADERROWS = 0; /** * 表格内容字体 */ public static Font CONTENTFONT = new Font(baseFont, 9, Font.NORMAL); /** * PDF表格样式 */ private static PdfPCell cell = new PdfPCell(); /** * 获取表格 */ public static PdfPCell getCell() { // 水平居中 cell.setHorizontalAlignment(Element.ALIGN_CENTER); // 垂直居中 cell.setVerticalAlignment(Element.ALIGN_MIDDLE); // 边距 cell.setPadding(1); // 行高 cell.setMinimumHeight(22); // 不换行 // cell.setNoWrap(true); // 颜色淡化 // cell.setBorderColor(Color.decode("#EBEEF5")); cell.setBorderColor(new BaseColor(1)); return cell; } /** * 获取表格并赋值 */ public static PdfPCell getCell(Paragraph content) { cell = getCell(); // 设置内容 cell.setPhrase(content); return cell; } /** * @Description 生成PDF表格 * @param titleNum * 列数 * @param tableWidth * 列宽 * @param titles * 标题集合 * @param contents * 内容集合 * @param headerRows * 是否再次加载表头 * @return * @throws Exception */ public static PdfPTable getPDFTable(int[] tableWidth, String[] titles, List<Object> contents, int headerRows) throws Exception { // 创建表格对象 // 列数 PdfPTable table = new PdfPTable(titles.length); // 表格宽度百分比 table.setWidthPercentage(WIDTHPERCENTAGE); table.setSpacingBefore(20); table.setSpacingAfter(20); // 列宽百分比 if (tableWidth != null) table.setWidths(tableWidth); // 翻页加载表头 if (headerRows == HEADERROWS) table.setHeaderRows(HEADERROWS); // 标题集合 String[] pdfTitles = titles; if (pdfTitles != null && pdfTitles.length > 0) { // 标题 for (String pdfTitle : pdfTitles) { PdfPCell title = getCell(new Paragraph(pdfTitle, TITLEFONT)); table.addCell(title); } } // 内容集合 if (contents != null && contents.size() > 0) { Field[] fields = contents.getClass().getDeclaredFields(); String[] fieldNames = new String[fields.length]; for (int i = 0; i < fields.length; i++) { fieldNames[i] = fields[i].getName(); } } // 内容集合 if (contents != null && contents.size() > 0) { for (Object obj : contents) { Field[] fields = obj.getClass().getDeclaredFields(); String[] fieldNames = new String[fields.length]; for (int i = 0; i < fields.length; i++) { fieldNames[i] = fields[i].getName(); String firstLetter = fieldNames[i].substring(0, 1).toUpperCase(); String getter = "get" + firstLetter + fieldNames[i].substring(1); Method method = obj.getClass().getMethod(getter, new Class[] {}); Object value = method.invoke(obj, new Object[] {}); PdfPCell content = getCell(new Paragraph(String.valueOf(value), CONTENTFONT)); table.addCell(content); } // 撑行数,否则最后一行会消失 table.addCell(""); table.completeRow(); } } return table; } /** * @param content 段落内容 * @param top 上边距 * @param bottom 下边距 * @param align 居中 * @param type 标题类别 * @return * @throws Exception */ public static Paragraph getPDFParagraph(String content, int top, int bottom, int align, int type) throws Exception { Paragraph paragraph = null; if (type == 1) { paragraph = new Paragraph(content, PDFTITLEFONT); } else { paragraph = new Paragraph(content, PDFTITLEFONT1); } paragraph.setSpacingAfter(top); paragraph.setSpacingBefore(bottom); paragraph.setAlignment(align); return paragraph; } }
import com.itextpdf.text.Document; import com.itextpdf.text.pdf.BaseFont; import com.itextpdf.text.pdf.PdfContentByte; import com.itextpdf.text.pdf.PdfPageEventHelper; import com.itextpdf.text.pdf.PdfTemplate; import com.itextpdf.text.pdf.PdfWriter; /** * @Description 分页工具 * @author ry * @date 2019年7月12日 */ public class PDFMaker extends PdfPageEventHelper { /** 这个PdfTemplate实例用于保存总页数 */ public PdfTemplate tpl; /** 页码字体 */ public BaseFont helv; @Override public void onCloseDocument(PdfWriter writer, Document arg1) { tpl.beginText(); tpl.setFontAndSize(helv, 12); tpl.setTextMatrix(0, 0); tpl.showText("" + (writer.getPageNumber() - 1)); tpl.endText(); } /* * (non-Javadoc) * * @see * com.lowagie.text.pdf.PdfPageEventHelper#onEndPage(com.lowagie.text.pdf * .PdfWriter, com.lowagie.text.Document) */ @Override public void onEndPage(PdfWriter writer, Document document) { PdfContentByte cb = writer.getDirectContent(); cb.saveState(); String text = " Page " + writer.getPageNumber() + " of "; float textSize = helv.getWidthPoint(text, 9); float textBase = document.bottom(); cb.beginText(); cb.setFontAndSize(helv, 9); // for odd pagenumbers, show t cb.setTextMatrix(document.left(), textBase); cb.showText(text); cb.endText(); cb.addTemplate(tpl, document.left() + textSize, textBase); cb.restoreState(); } /* * (non-Javadoc) * * @see * com.lowagie.text.pdf.PdfPageEventHelper#onOpenDocument(com.lowagie.text * .pdf.PdfWriter, com.lowagie.text.Document) */ @Override public void onOpenDocument(PdfWriter writer, Document arg1) { try { // initialization of the template tpl = writer.getDirectContent().createTemplate(100, 100); // tpl.setBoundingBox(new Rectangle(0, 0, 10, 10)); // initialization of the font helv = BaseFont.createFont("Helvetica", BaseFont.WINANSI, false); } catch (Exception e) { } } }
3.PDF文件流下载
后台返回itext生成的输出流,这里使用工具类生成了多个表格。
public void exportPDFTest() { HttpServletRequest request = ServletActionContext.getRequest(); SysUserInfo user = (SysUserInfo) request.getSession().getAttribute("user"); try { HttpServletResponse response = ServletActionContext.getResponse(); response.setContentType("text/json"); String resId = request.getParameter("resId"); if (resId == null || resId.trim().equals("")) { SysLogUtil.saveLog(this.logService, "ID不能为空", user.getAccount(), request, String.valueOf(user.getId())); return; } ByteArrayOutputStream baos = new ByteArrayOutputStream();// 构建字节输出流 // 实例化文档对象 Document document = new Document(PageSize.A4, 10, 10, 10, 10); // 创建 PdfWriter 对象 文件的输出路径+文件的实际名称 PdfWriter writer = PdfWriter.getInstance(document, baos);// 设置分页 // writer.setPageEvent(new PDFMaker()); document.open();// 打开文档 // 创建一个段落 document.add(PDFUtil.getPDFParagraph("测试PDF标题", 0, 20, Element.ALIGN_CENTER, 1)); // 标题 String[] title = { "ID", "姓名", "年龄", "生日", "出生地", "身份证", "住址" }; // 列宽 int tableWidth[] = { 10, 15, 15, 15, 15, 15, 15 }; Map<String, Object> map = this.service.getPolicyOptimization(Long.parseLong(resId)); if (map != null) { if (map.get("nullList") != null) { // 添加一个段落 document.add(PDFUtil.getPDFParagraph("表格一", 0 ,20, Element.ALIGN_LEFT, 2)); List list = (List<RawPolicyInfo>) map.get("nullList"); // 获取PDFTable PdfPTable table = PDFUtil.getPDFTable(tableWidth, title, list, 0); // 添加进文档 document.add(table); } if (map.get("ksList") != null) { // 添加一个段落 document.add(PDFUtil.getPDFParagraph("表格二", 0, 20, Element.ALIGN_LEFT, 2)); List list = (List<RawPolicyInfo>) map.get("ksList"); // 获取PDFTable PdfPTable table = PDFUtil.getPDFTable(tableWidth, title, list, 0); // 添加进文档 document.add(table); } if (map.get("ryMap") != null) { // 添加一个段落 document.add(PDFUtil.getPDFParagraph("表格三", 0, 20, Element.ALIGN_LEFT, 2)); Map maps = (Map)map.get("ryMap"); maps.values(); for (Object value : maps.values()) { List list = (List<RawPolicyInfo>)value; // 获取PDFTable PdfPTable table = PDFUtil.getPDFTable(tableWidth, title, list, 0); document.add(table); } } if (map.get("hbMap") != null) { // 添加一个段落 document.add(PDFUtil.getPDFParagraph("表格四", 0, 20, Element.ALIGN_LEFT, 2)); Map maps = (Map)map.get("hbMap"); maps.values(); for (Object value : maps.values()) { List list = (List<RawPolicyInfo>)value; // 获取PDFTable PdfPTable table = PDFUtil.getPDFTable(tableWidth, title, list, 0); document.add(table); } } if (map.get("ctMap") != null) { // 添加一个段落 document.add(PDFUtil.getPDFParagraph("表格五", 0, 20, Element.ALIGN_LEFT, 2)); Map maps = (Map)map.get("ctMap"); maps.values(); for (Object value : maps.values()) { List list = (List<RawPolicyInfo>)value; // 获取PDFTable PdfPTable table = PDFUtil.getPDFTable(tableWidth, title, list, 0); document.add(table); } } } // 关闭文档 if (document != null) { document.close(); } if (baos != null) { try { baos.close(); } catch (IOException e) { e.printStackTrace(); } } String fileName = "测试PDF.pdf"; String agent = (String) request.getHeader("USER-AGENT"); if (agent != null && agent.indexOf("MSIE") == -1) { // FF fileName = "=?UTF-8?B?" + (new String(Base64.encodeBase64(fileName.getBytes("UTF-8")))) + "?="; response.setHeader("Content-Disposition", "attachment; filename=" + fileName); } else { // IE fileName = new String(fileName.getBytes("GBK"), "ISO-8859-1"); response.setHeader("Content-Disposition", "attachment; filename=" + fileName); } OutputStream os = response.getOutputStream(); // 设置文件大小 // response.setContentLength((int) f.length()); os.write(baos.toByteArray()); } catch (Exception e) { e.printStackTrace(); } }
//jsp页面调用 function exportPDF() { var url="exportPDFTest.action?resId="+nowSelectedFw; window.location.href=url; }
4.效果图