需求背景
在工作中经常会有生成pdf文件的需求,大多数情况下,我们只需要使用pdf模版添加表单域,就足以胜任了。但是有一些特殊的需求,需要生成较为复杂的文件,如动态数据表格、插入图像等。
这时候,我们就可以使用拼接的方式,将pdf文件内容一段段拼上去,组合成一个pdf文件,来灵活的操纵文件的排版与内存形式。
itext 的使用
依赖
<dependency> <groupid>com.itextpdf</groupid> <artifactid>itextpdf</artifactid> <version>5.5.13</version> </dependency> <!-- https://mvnrepository.com/artifact/com.itextpdf/itext-asian --> <dependency> <groupid>com.itextpdf</groupid> <artifactid>itext-asian</artifactid> <version>5.2.0</version> </dependency>
简单示例
生成一个内容为“hello world”的pdf文件
import com.itextpdf.text.*; import com.itextpdf.text.pdf.pdfwriter; import java.io.filenotfoundexception; import java.io.fileoutputstream; import java.util.logging.level; import java.util.logging.logger; /** * 生成一个内容为“hello world”的pdf文件 * @author ym */ public class helloworld { public static void main(string[] args) { string file_dir = "./"; // 项目根目录:盘符:/.../.../项目名称,注意:点号并不表示当前类文件所在的目录,而是项目目录下 //step 1—create a document. document document = new document(); try { //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(); } catch (documentexception ex) { logger.getlogger(helloworld.class.getname()).log(level.severe, null, ex); } catch (filenotfoundexception ex) { logger.getlogger(helloworld.class.getname()).log(level.severe, null, ex); } } }
基础设置(页面大小、边距、字体等)
//页面大小 rectangle rect = new rectangle(pagesize.a4.rotate()); //页面背景色 rect.setbackgroundcolor(basecolor.orange); // page , 外边距 marginleft marginright margintop marginbottom document doc = new document(rect,90, 90, 30, 40); // 新开一页 doc.newpage(); /** * 段落设置 */ paragraph titleparagraph = new paragraph("hello world!", getchinesetitlefont()); titleparagraph.setalignment(element.align_center);// 居中 titleparagraph.setfirstlineindent(24);// 首行缩进 titleparagraph.setleading(35f);// 行间距 titleparagraph.setspacingbefore(5f);// 设置上空白 titleparagraph.setspacingafter(10f);// 设置段落下空白 //支持中文 设置字体,字体颜色、大小等 public font getchinesetitlefont() throws runtimeexception { font chinesefont = null; try { /** * name – the name of the font or its location on file * encoding – the encoding to be applied to this font * embedded – true if the font is to be embedded in the pdf */ basefont simpchinese = basefont.createfont("stsongstd-light", "unigb-ucs2-h", basefont.not_embedded); chinesefont = new font(simpchinese, 15, font.bold, basecolor.black); } catch (documentexception e) { log.error("getchinesefont" ,"字体异常",e); throw new runtimeexception("getchinesefont字体异常",e); } catch (ioexception e) { log.error("getchinesefont" ,"字体异常",e); throw new runtimeexception("getchinesefont字体异常",e); } return chinesefont; }
段落内部,特殊设置关键字 字体或颜色
// 文本内容 string content = "this is a sample text with different colors."; string[] words = content.split(" "); // 将文本拆分为单词 for (string word : words) { chunk chunk = new chunk(word); // 创建一个新的 chunk // 如果单词是 "different",则设置为红色 if (word.equals("different")) { chunk.setforegroundcolor(basecolor.red); } // 如果单词是 "colors.",则设置为蓝色 if (word.equals("colors.")) { chunk.setforegroundcolor(basecolor.blue); } contentparagraph.add(chunk); // 将 chunk 添加到段落中 contentparagraph.add(" "); // 添加单词之间的空格 } document.add(contentparagraph); // 将段落添加到文档中
生成动态表格
// 创建一个包含5列的表格 pdfptable table = new pdfptable(5); // 添加表头 table.addcell("header 1"); table.addcell("header 2"); table.addcell("header 3"); table.addcell("header 4"); table.addcell("header 5"); // 添加动态数据到表格 for (int i = 0; i < 10; i++) { table.addcell("data " + i + ", 1"); table.addcell("data " + i + ", 2"); table.addcell("data " + i + ", 3"); table.addcell("data " + i + ", 4"); table.addcell("data " + i + ", 5"); } document.add(table); /** * 如果需要更精细的控制属性 */ cell = new pdfpcell(new phrase("title1",fontchinese)); cell.setcolspan(1);//设置所占列数 cell.setrowspan(1);//合并行 cell.sethorizontalalignment(element.align_center);//设置水平居中 cell.setverticalalignment(element.align_middle);//设置垂直居中 cell.setfixedheight(30);//设置高度 table.addcell(cell);
页脚展示页数
pdfwriter writer = pdfwriter.getinstance(document, new fileoutputstream(file_dir + "createsamplepdf.pdf")); writer.setpageevent(new footerevent()); public class footerevent extends pdfpageeventhelper { //总页数 pdftemplate totalpage; //字体 font font; { try { basefont chinese = basefont.createfont("stsong-light", "unigb-ucs2-h", basefont.not_embedded); font = new font(chinese,10); } catch (documentexception | ioexception e) { e.printstacktrace(); } } //打开文档时,创建一个总页数的模版 @override public void onopendocument(pdfwriter writer, document document) { pdfcontentbyte cb = writer.getdirectcontent(); totalpage = cb.createtemplate(50, 9); } @override public void onendpage(pdfwriter writer, document document) { //创建一个两列的表格 pdfptable table = new pdfptable(2); try { table.settotalwidth(pagesize.a4.getwidth());//总宽度为a4纸张宽度 table.setlockedwidth(true);//锁定列宽 table.setwidths(new int[]{50, 50});//设置每列宽度 pdfpcell cell = new pdfpcell(new phrase("第"+document.getpagenumber() + " 页,共", font)); cell.sethorizontalalignment(element.align_right);//设置水平右对齐 cell.setverticalalignment(element.align_middle);//设置垂直居中 cell.disableborderside(15);//隐藏全部边框 table.addcell(cell); pdfpcell cell1 = new pdfpcell(image.getinstance(totalpage));//共 页 cell1.sethorizontalalignment(element.align_left);//设置水平左对齐 cell1.setverticalalignment(element.align_middle);//设置垂直居中 cell1.disableborderside(15);//隐藏全部边框 table.addcell(cell1); table.writeselectedrows(0, -1, 0, 30, writer.getdirectcontent()); } catch (exception e) { throw new exceptionconverter(e); } } @override public void onclosedocument(pdfwriter writer, document document) { string text = "" +string.valueof(writer.getpagenumber()) +"页"; columntext.showtextaligned(totalpage, element.align_middle, new paragraph(text, font), 0, 0, 0); } }
其他
设置密码
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"));
添加水印(背景图)
//图片水印 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();
目录
// code 1 document.add(new chunk("chapter 1").setlocaldestination("1")); document.newpage(); document.add(new chunk("chapter 2").setlocaldestination("2")); document.add(new paragraph(new chunk("sub 2.1").setlocaldestination("2.1"))); document.add(new paragraph(new chunk("sub 2.2").setlocaldestination("2.2"))); document.newpage(); document.add(new chunk("chapter 3").setlocaldestination("3")); // code 2 pdfcontentbyte cb = writer.getdirectcontent(); pdfoutline root = cb.getrootoutline(); // code 3 @suppresswarnings("unused") pdfoutline oline1 = new pdfoutline(root, pdfaction.gotolocalpage("1", false), "chapter 1"); pdfoutline oline2 = new pdfoutline(root, pdfaction.gotolocalpage("2", false), "chapter 2"); oline2.setopen(false); @suppresswarnings("unused") pdfoutline oline2_1 = new pdfoutline(oline2, pdfaction.gotolocalpage("2.1", false), "sub 2.1"); @suppresswarnings("unused") pdfoutline oline2_2 = new pdfoutline(oline2, pdfaction.gotolocalpage("2.2", false), "sub 2.2"); @suppresswarnings("unused") pdfoutline oline3 = new pdfoutline(root, pdfaction.gotolocalpage("3", false), "chapter 3");
header, footer
pdfwriter writer = pdfwriter.getinstance(doc, new fileoutputstream(file_dir + "setheaderfooter.pdf")); writer.setpageevent(new pdfpageeventhelper() { public void onendpage(pdfwriter writer, document document) { pdfcontentbyte cb = writer.getdirectcontent(); cb.savestate(); cb.begintext(); basefont bf = null; try { bf = basefont.createfont(basefont.helvetica, basefont.winansi, basefont.embedded); } catch (exception e) { e.printstacktrace(); } cb.setfontandsize(bf, 10); //header float x = document.top(-20); //左 cb.showtextaligned(pdfcontentbyte.align_left, "h-left", document.left(), x, 0); //中 cb.showtextaligned(pdfcontentbyte.align_center, writer.getpagenumber()+ " page", (document.right() + document.left())/2, x, 0); //右 cb.showtextaligned(pdfcontentbyte.align_right, "h-right", document.right(), x, 0); //footer float y = document.bottom(-20); //左 cb.showtextaligned(pdfcontentbyte.align_left, "f-left", document.left(), y, 0); //中 cb.showtextaligned(pdfcontentbyte.align_center, writer.getpagenumber()+" page", (document.right() + document.left())/2, y, 0); //右 cb.showtextaligned(pdfcontentbyte.align_right, "f-right", document.right(), y, 0); cb.endtext(); cb.restorestate(); } }); doc.open(); doc.add(new paragraph("1 page")); doc.newpage(); doc.add(new paragraph("2 page")); doc.newpage(); doc.add(new paragraph("3 page")); doc.newpage(); doc.add(new paragraph("4 page"));
分割 pdf
fileoutputstream out = new fileoutputstream(file_dir + "splitpdf.pdf"); document document = new document(); pdfwriter.getinstance(document, out); document.open(); document.add(new paragraph("1 page")); document.newpage(); document.add(new paragraph("2 page")); document.newpage(); document.add(new paragraph("3 page")); document.newpage(); document.add(new paragraph("4 page")); document.close(); pdfreader reader = new pdfreader(file_dir + "splitpdf.pdf"); document dd = new document(); pdfwriter writer = pdfwriter.getinstance(dd, new fileoutputstream(file_dir + "splitpdf1.pdf")); dd.open(); pdfcontentbyte cb = writer.getdirectcontent(); dd.newpage(); cb.addtemplate(writer.getimportedpage(reader, 1), 0, 0); dd.newpage(); cb.addtemplate(writer.getimportedpage(reader, 2), 0, 0); dd.close(); writer.close(); document dd2 = new document(); pdfwriter writer2 = pdfwriter.getinstance(dd2, new fileoutputstream(file_dir + "splitpdf2.pdf")); dd2.open(); pdfcontentbyte cb2 = writer2.getdirectcontent(); dd2.newpage(); cb2.addtemplate(writer2.getimportedpage(reader, 3), 0, 0); dd2.newpage(); cb2.addtemplate(writer2.getimportedpage(reader, 4), 0, 0); dd2.close(); writer2.close();
合并 pdf
pdfreader reader1 = new pdfreader(file_dir + "splitpdf1.pdf"); pdfreader reader2 = new pdfreader(file_dir + "splitpdf2.pdf"); fileoutputstream out = new fileoutputstream(file_dir + "mergepdf.pdf"); document document = new document(); pdfwriter writer = pdfwriter.getinstance(document, out); document.open(); pdfcontentbyte cb = writer.getdirectcontent(); int totalpages = 0; totalpages += reader1.getnumberofpages(); totalpages += reader2.getnumberofpages(); java.util.list<pdfreader> readers = new arraylist<pdfreader>(); readers.add(reader1); readers.add(reader2); int pageofcurrentreaderpdf = 0; iterator<pdfreader> iteratorpdfreader = readers.iterator(); // loop through the pdf files and add to the output. while (iteratorpdfreader.hasnext()) { pdfreader pdfreader = iteratorpdfreader.next(); // create a new page in the target for each source page. while (pageofcurrentreaderpdf < pdfreader.getnumberofpages()) { document.newpage(); pageofcurrentreaderpdf++; pdfimportedpage page = writer.getimportedpage(pdfreader, pageofcurrentreaderpdf); cb.addtemplate(page, 0, 0); } pageofcurrentreaderpdf = 0; } out.flush(); document.close(); out.close();
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论