itextpdfJAVA输出PDF⽂档使⽤JAVA⽣成PDF的时候,还是有些注意事项需要处理的。
第⼀、中⽂问题,默认的itext是不⽀持中⽂的,想要⽀持,需要做些处理。
1、直接引⽤操作系统的中⽂字体库⽀持,由于此⽅案限制性强,⼜绑定了操作系统,所以此处不做实现,有兴趣可在⽹上搜索看看。
2、引⽤itext-asian.jar包的字体⽀持,代码稍后上。
itext pdf引⼊中⽂常见异常: com.itextpdf.text.DocumentException: Font 'STSongStd-Light' with 'UniGB-UCS2-H' is not recognized. 解决⽅案:a、引⼊操作系统字体;2、将字体维护进jar包中,如果没有,直接找到字体放⼊对应jar包中,如果是路径错误,则更改包路径;3、通过itext-asian.jar来加载中⽂包。
第⼆、表格中的设置,特别是上中下,左中右,不同的对象有不同的枚举实现,刚⼊⼿很容易混淆。
其外是前景⾊,背景⾊,表格颜⾊等等。
第三、输出图⽚,很容易报错。
itext pdf常见输出图⽚异常: An error exists on this page. Acrobat may not display the page correctly. Please contact the person who created the PDF document to correct the problem. 原因:PdfContentByte在addImage的时候需要在beginText()和endText()范围以外调⽤,否则⽣成的PDF就会报上述错误。
⽰例:1package com.itext.test;23import java.io.File;4import java.io.FileOutputStream;5import java.io.IOException;6import java.io.InputStream;7import java.util.ArrayList;8import java.util.List;9import java.util.Random;1011import com.itextpdf.text.BaseColor;12import com.itextpdf.text.Document;13import com.itextpdf.text.DocumentException;14import com.itextpdf.text.Element;15import com.itextpdf.text.Font;16import com.itextpdf.text.Image;17import com.itextpdf.text.PageSize;18import com.itextpdf.text.Paragraph;19import com.itextpdf.text.Rectangle;20import com.itextpdf.text.pdf.BarcodeQRCode;21import com.itextpdf.text.pdf.BaseFont;22import com.itextpdf.text.pdf.PdfContentByte;23import com.itextpdf.text.pdf.PdfGState;24import com.itextpdf.text.pdf.PdfPCell;25import com.itextpdf.text.pdf.PdfPTable;26import com.itextpdf.text.pdf.PdfPageEventHelper;27import com.itextpdf.text.pdf.PdfWriter;2829public class D {3031private static String path = "docs/"; // ⽣成PDF后的存放路径32private static final String logoPath = "logo.png";3334public static void main(String[] args) {35// T t = new T();36 initPDF(initData());37 }3839/**40 * 初始化PDF41 *42 * @param apis43*/44public static void initPDF(List<Api> apis) {45 File folder = new File(path);46if (!folder.exists())47 folder.mkdirs(); // 创建⽬录48 Document doc = null;49try {50// 中⽂字体,要有itext-asian.jar⽀持(默认的itext.jar是不⽀持中⽂的)51 BaseFont bfchinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);52 Rectangle pageSize = new Rectangle(PageSize.A4); // 页⾯⼤⼩设置为A453 doc = new Document(pageSize, 20, 20, 40, 40); // 创建doc对象并设置边距54 PdfWriter writer = PdfWriter.getInstance(doc, new FileOutputStream(folder.getAbsolutePath() + File.separator + "API⽂档.pdf"));55 writer.setPageEvent(new SdkPdfPageEvent());56 doc.open();57 doc.addAuthor("Ares-xby");58 doc.addSubject("SDK附属API⽂档");59 doc.addTitle("API⽂档");60 BaseColor borderColor = new BaseColor(90, 140, 200);61 BaseColor bgColor = new BaseColor(80, 130, 180);62for (Api api : apis) {63 PdfPTable table = new PdfPTable({0.25f, 0.25f, 0.25f, 0.25f});64// table.setWidthPercentage(100); // 设置table宽度为100%65// table.setHorizontalAlignment(PdfPTable.ALIGN_CENTER); // 设置table居中显⽰66for (int i = 0; i < api.getParams().size(); i++) {67if (i == 0) {68// row 169 table.addCell(createCell("API", bfchinese, borderColor, bgColor));70 table.addCell(createCell(api.getApiName(), 12, bfchinese, 3, null, borderColor, bgColor));71// row 272 table.addCell(createCell("描述", bfchinese, borderColor));73 table.addCell(createCell(api.getApiDesc(), 12, bfchinese, 3, null, borderColor));74 } else {75 table.addCell(createCell(api.getParams().get(i).getParamName(), 10, bfchinese, null, Paragraph.ALIGN_RIGHT, borderColor));76 table.addCell(createCell(api.getParams().get(i).getParamName(), 10, bfchinese, null, null, borderColor));77 table.addCell(createCell(api.getParams().get(i).getParamType(), 10, bfchinese, null, null, borderColor));78 table.addCell(createCell(api.getParams().get(i).getParamDesc(), 10, bfchinese, null, null, borderColor));79 }80 }81 doc.add(table);82 }83// ⼆维码84 BarcodeQRCode qrcode = new BarcodeQRCode("", 1, 1, null);85 Image qrcodeImage = qrcode.getImage();86 qrcodeImage.setAbsolutePosition(10, 600);87 qrcodeImage.scalePercent(200);88 doc.add(qrcodeImage);89 doc.close();90 System.out.println("init pdf over.");91 } catch (DocumentException e) {92 e.printStackTrace();93 } catch (IOException e) {94 e.printStackTrace();95 } finally {96if (doc != null)97 doc.close();98 }99100 }101102public static List<Api> initData() {103 List<Api> list = new ArrayList<Api>();104for (int i = 0; i < 100; i++) {105 Api api = new Api();106 api.setApiName("api-" + i);107 api.setApiDesc("描述-" + i);108int paramSize = new Random().nextInt(20);109 List<Params> paramList = new ArrayList<Params>();110for (int j = 0; j < paramSize; j++) {111 Params param = new Params();112 param.setParamName("param-" + i + "-" + j);113 param.setParamType("paramType-" + i + "-" + j);114 param.setParamDesc("描述-" + i + "-" + j);115 paramList.add(param);116 }117 api.setParams(paramList);118 list.add(api);119 }120 System.out.println("init data over. size=" + list.size());121return list;122 }123// ⽤於⽣成cell124private static PdfPCell createCell(String text, BaseFont font, BaseColor borderColor) {125return createCell(text, 12, font, null, null, borderColor, null);126 }127// ⽤於⽣成cell128private static PdfPCell createCell(String text, BaseFont font, BaseColor borderColor, BaseColor bgColor) {129return createCell(text, 12, font, null, null, borderColor, bgColor);130 }131// ⽤於⽣成cell132private static PdfPCell createCell(String text, int fontsize, BaseFont font, Integer colspan, Integer align, BaseColor borderColor) {133return createCell(text, fontsize, font, colspan, align, borderColor, null);134 }135136/**137 * ⽤於⽣成cell138 * @param text Cell⽂字内容139 * @param fontsize 字体⼤⼩140 * @param font 字体141 * @param colspan 合并列数量142 * @param align 显⽰位置(左中右,Paragraph对象)143 * @param borderColor Cell边框颜⾊144 * @param bgColor Cell背景⾊145 * @return146*/147private static PdfPCell createCell(String text, int fontsize, BaseFont font, Integer colspan, Integer align, BaseColor borderColor, BaseColor bgColor) { 148 Paragraph pagragraph = new Paragraph(text, new Font(font, fontsize));149 PdfPCell cell = new PdfPCell(pagragraph);150 cell.setFixedHeight(20);151 cell.setVerticalAlignment(Element.ALIGN_MIDDLE); // 上中下,Element对象152if (align != null)153 cell.setHorizontalAlignment(align);154if (colspan != null && colspan > 1)155 cell.setColspan(colspan);156if (borderColor != null)157 cell.setBorderColor(borderColor);158if (bgColor != null)159 cell.setBackgroundColor(bgColor);160return cell;161 }162163/**164 * SDK中PDF相关的PageEvent165*/166static class SdkPdfPageEvent extends PdfPageEventHelper {167168 @Override169public void onStartPage(PdfWriter writer, Document document) {170// ⽔印(water mark)171 PdfContentByte pcb = writer.getDirectContent();172 pcb.saveState();173 BaseFont bf;174try {175 bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);176 pcb.setFontAndSize(bf, 36);177 } catch (DocumentException e) {178 e.printStackTrace();179 } catch (IOException e) {180 e.printStackTrace();181 }182// 透明度设置183 PdfGState gs = new PdfGState();184 gs.setFillOpacity(0.2f);185 pcb.setGState(gs);186187 pcb.beginText();188 pcb.setTextMatrix(60, 90);189 pcb.showTextAligned(Element.ALIGN_LEFT, "XX公司有限公司", 200, 300, 45);190191 pcb.endText();192 pcb.restoreState();193 }194195 @Override196public void onEndPage(PdfWriter writer, Document document) {197// 页眉、页脚198 PdfContentByte pcb = writer.getDirectContent();199try {200 pcb.setFontAndSize(BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED), 10);201 } catch (Exception e) {202 e.printStackTrace();203 } // ⽀持中⽂字体204 pcb.saveState();205try {206// pcb.addImage()⽅法要在pcb.beginText();pcb.endText();之外调⽤,207// 否则⽣成的PDF打开时会报错: An error exists on this page. Acrobat may not display the page correctly. Please contact the person who created the PDF document to correct the problem.208byte[] logoBytes = new byte[1000 * 1024]; // 此处数组⼤⼩要⽐logo图⽚⼤⼩要⼤, 否则图⽚会损坏;能够直接知道图⽚⼤⼩最好不过.209 InputStream logoIs = getClass().getResourceAsStream(logoPath);210if(logoIs != null){211int logoSize = logoIs.read(logoBytes); // 尝试了⼀下,此处图⽚复制不完全,需要专门写个⽅法,将InputStream转换成Byte数组,详情参考org.apache.io.IOUtils.java的toByteArray(InputStream in)⽅法212if(logoSize > 0){213byte[] logo = new byte[logoSize];214 System.arraycopy(logoBytes, 0, logo, 0, logoSize);215 Image image = Image.getInstance(logo);// 如果直接使⽤logoBytes,并且图⽚是jar包中的话,会报图⽚损坏异常;本地图⽚可直接getInstance时候使⽤路径。