生成 PDF 全攻略【2】在已有PDF上添加内容
项目在变,需求在变,不变的永远是敲击键盘的程序员.....
PDF 生成后,有时候需要在PDF上面添加一些其他的内容,比如文字,图片....
经历几次失败的尝试,终于获取到了正确的代码书写方式。
在此记录总结,方便下次以不变应万变,需要的 jar 请移步:生成PDF全攻略
PdfReader reader = new PdfReader("E:\\A.pdf");
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("E:\\B.pdf"));
PdfContentByte overContent = stamper.getOverContent(1);
上述的这段代码算是在原有 PDF 上面添加内容的核心代码,具体流程如下

- 如果看官老爷够仔细的话,该代码是将原 A.pdf 读取,然后将它写入 B.pdf,然后操作 B.pdf。
- 可能有的看官老爷会说,将 A 读取,然后在写入 A 中,这样肯定是不行的,在读取的时候 A 已经被加载了,不能进行修改。
- 我不喜欢这种方式,因为原 PDF 的信息已经存储在数据库中,其中包括 PDF 的服务器路径、旧名称、新名称、类型......
- 这样就会多出一次数据库变更操作,因为这里PDF名称需要变更,而且鬼知道后续需求还会怎么变。
- 这里急需 只在 PDF 中添加内容,其他的什么都不变,将代码稍微调整了一下。
FileUtil.fileChannelCopy(A.pdf,A + "tmp".pdf));
PdfReader reader = new PdfReader(A + "tmp".pdf);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(A.pdf));
PdfContentByte overContent = stamper.getOverContent(1);
代码流程就变做下面这个样子

- 这里引入了管道复制文件,将A 复制一份,读取副本,然后写回到原 PDF A 中,最后当然需要删除副本文件。
- 到这里,无论后续需求怎么变,保证了pdf 的其他属性不变,就能从容面对。
管道复制代码如下:
public static void fileChannelCopy(File sources, File dest) {
try {
FileInputStream inputStream = new FileInputStream(sources);
FileOutputStream outputStream = new FileOutputStream(dest);
FileChannel fileChannelin = inputStream.getChannel();//得到对应的文件通道
FileChannel fileChannelout = outputStream.getChannel();//得到对应的文件通道
fileChannelin.transferTo(0, fileChannelin.size(), fileChannelout);//连接两个通道,并且从in通道读取,然后写入out通道
inputStream.close();
fileChannelin.close();
outputStream.close();
fileChannelout.close();
} catch (Exception e) {
e.printStackTrace();
}
}
完整的在已有PDF添加其他内容代码如下:
FileUtil.fileChannelCopy(new File("E:\\A.pdf"),new File("E:\\A+"tmp".pdf"));
PdfReader reader = new PdfReader("E:\\A+"tmp".pdf");
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("E:\\A.pdf"));
PdfContentByte overContent = stamper.getOverContent(1);
//添加文字
BaseFont font = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
overContent.beginText();
overContent.setFontAndSize(font, 10);
overContent.setTextMatrix(200, 200);
overContent.showTextAligned(Element.ALIGN_CENTER,"需要添加的文字",580,530,0);
overContent.endText();
//添加图片
PdfDictionary pdfDictionary = reader.getPageN(1);
PdfObject pdfObject = pdfDictionary.get(new PdfName("MediaBox"));
PdfArray pdfArray = (PdfArray) pdfObject;
Image image = Image.getInstance("D:\\1.jpg");
image.setAbsolutePosition(100,100);
overContent.addImage(image);
//添加一个红圈
overContent.setRGBColorStroke(0xFF, 0x00, 0x00);
overContent.setLineWidth(5f);
overContent.ellipse(250, 450, 350, 550);
overContent.stroke();
stamper.close();
生成 PDF 全攻略【2】在已有PDF上添加内容的更多相关文章
- 生成 PDF 全攻略【1】初体验
经历过多少踩坑,翻看过多少类似博客,下载过多少版本的Jar,才能摸索出正确的代码书写方式,才能实现项目经理需求分析书中的功能点. 本文借一次 JavaEE 生成PDF的颠簸的实现过程,描述中小公司程序 ...
- Xcode 4.1~4.6 + iOS 5、iOS 6免证书(iDP)开发+真机调试+生成IPA全攻略
原创文章,欢迎分享:未经许可,不得转载:版权所有,侵权必究 开发环境使用的是目前为止最新的稳定版软件:Mac OS X Lion 10.7 + Xcode 4.1 目前Xcode 4.2 Previe ...
- Windows Socket五种I/O模型——代码全攻略(转)
Winsock 的I/O操作: 1. 两种I/O模式 阻塞模式:执行I/O操作完成前会一直进行等待,不会将控制权交给程序.套接字 默认为阻塞模式.可以通过多线程技术进行处理. 非阻塞模式:执行I/O操 ...
- 用C#制作PDF文件全攻略
用C#制作PDF文件全攻略 目 录 前 言... 3 第一部分 iText的简单应用... 4 第一章 创建一个Document 4 第一步 创建一个Document实例:... 5 第二步 ...
- 取代奶瓶Minidwep-gtk破解WPA 全攻略
取代奶瓶Minidwep-gtk 破 WPA 全攻略 目录 1. CDlinux 下使用 minidwepgtk 获取握手包并使用自带的字典破解 2. 自带的字典破解不出密码时使用 U 盘外挂字典继 ...
- 【C#代码实战】群蚁算法理论与实践全攻略——旅行商等路径优化问题的新方法
若干年前读研的时候,学院有一个教授,专门做群蚁算法的,很厉害,偶尔了解了一点点.感觉也是生物智能的一个体现,和遗传算法.神经网络有异曲同工之妙.只不过当时没有实际需求学习,所以没去研究.最近有一个这样 ...
- Moon.Orm3.8技术全攻略
Moon.ORM技术全攻略 一.绪论 本文主要是针对Moon.ORM的技术的讨论及其使用使用指导.如有其它疑问,请留言.本文主要针对Moon.ORM3.9版本,同时将会对4.0做一个技术预览.本文从 ...
- MyEclipse优化全攻略
(0) 吐槽 Eclipse仅仅是个半成品有木有?什么都须要自己安装插件,新手非常难用有木有? 安装上插件以后了版本号兼容和各种问题烦死人有木有? 都怪碎片和版本号乱公布有木有? IntelliJ I ...
- VSCode插件开发全攻略(六)开发调试技巧
更多文章请戳VSCode插件开发全攻略系列目录导航. 前言 在介绍完一些比较简单的内容点之后,我觉得有必要先和大家介绍一些开发中遇到的一些细节问题以及技巧,特别是后面一章节将要介绍WebView的知识 ...
随机推荐
- 实用CSS3的transform实现多种动画效果
查看效果:http://keleyi.com/a/bjad/b6x9q8gs.htm 以下是代码: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4. ...
- Javascript中prototype属性详解
在典型的面向对象的语言中,如java,都存在类(class)的概念,类就是对象的模板,对象就是类的实例.但是在Javascript语言体系中,是不存在类(Class)的概念的,javascript中不 ...
- 浏览器history对象
History 对象 history对象记录了用户曾经浏览过的页面(URL),并可以实现浏览器前进与后退相似导航的功能. 注意:从窗口被打开的那一刻开始记录,每个浏览器窗口.每个标签页乃至每个框架,都 ...
- C#图片处理常见方法性能比较
C#图片处理常见方法性能比较 来自:http://www.cnblogs.com/sndnnlfhvk/archive/2012/02/27/2370643.html 在.NET编程中,由于GDI ...
- 自定义AlertDialog控件的使用(AndroidStudio)
AlertDialog 第一种:可随意自定义控件 第一步:自定义弹出的页面 ,新建一个XML页面 如下图 不需要Activity 第二步:在主页面设置一个按钮弹出上图页面 (下面是主要代码 调用 ...
- Android 手机卫士--md5加密过程
在之前的文章中,我们将用户的密码使用SharedPreferences存储,我们打开/data/data/com.wuyudong.mobilesafe/shared_prefs文件夹下的 confi ...
- 关于UIView布局的总结
总结一下布局UIView 1.Laying out Subviews(布局子视图) 系统提供了相关的三个api - (void) layoutSubviews 在IOS5.1和之前的版本,此方法的缺省 ...
- iOS开发之功能模块--高仿Boss直聘的常用语的开发
首先上Boss直聘的功能界面截图,至于交互请读者现在Boss直聘去交互体验: 本人的公司项目要高仿Boss直聘的IM常用语的交互功能,居然花费了我前后17个小时完成,这回自己测试了很多遍,代码 ...
- Windows 10 IoT Serials 2 - Windows 10 IoT RTM 升级教程
7月29日,微软推出了Windows 10 for PC的正式版,其版本号是Build 10240.近两天官方说已经有4700万的下载安装量,同时这个数字还在不断攀升.另外,除了Windows 10 ...
- ORACLE临时表空间总结
临时表空间概念 临时表空间用来管理数据库排序操作以及用于存储临时表.中间排序结果等临时对象,当ORACLE里需要用到SORT的时候,并且当PGA中sort_area_size大小不够时,将会把数据放入 ...