一、:首先明确pdf的类型,在自己的开发过程中发现pdf也分几种类型。
我目前这里就指出常用两种:
一种是交互式pdf,他的组件可以读取,可以被编辑,比如liveCycle(Adobe LiveCycle Designer ES2)一款用于编辑pdf的软件。 (如果强行运行插入方法,不会报错,pdf内存也变大,但是就是无法看到图片)
一种是静态pdf,它里面的组件可以读取,不可编辑。
二、往pdf插入图片的两种方式
插入图片需要对插入位置进行定位,这就有两种方式
1:获取组件名,以组件为中心进行插入。同时可以将图片大小适应组件大小(比如我获取pdf一个签章域的名字)
public static void main(String[] args) throws Exception {
// 模板文件路径
String templatePath = "E://source.pdf";
// 生成的文件路径
String targetPath = "E://out.pdf";
// 关键字名
String fieldName = "SignatureField1";
// 图片路径
String imagePath = "E://00.jpg";
FileOutputStream fos = new FileOutputStream(targetPath);
// 读取模板文件
InputStream input = new FileInputStream(new File(templatePath));
PdfReader reader = new PdfReader(input);
PdfStamper stamper = new PdfStamper(reader, fos);
// 提取pdf中的表单
AcroFields form = stamper.getAcroFields();
form.addSubstitutionFont(BaseFont.createFont("STSong-Light","UniGB-UCS2-H", BaseFont.NOT_EMBEDDED));
// 通过域名获取所在页和坐标,左下角为起点
int pageNo = form.getFieldPositions(fieldName).get(0).page;
Rectangle signRect = form.getFieldPositions(fieldName).get(0).position;
float x = signRect.getLeft();
float y = signRect.getBottom();
//x = 20f;
//y = 40f;
// 读图片
Image image = Image.getInstance(imagePath);
// 获取操作的页面
PdfContentByte under = stamper.getOverContent(pageNo);
// 根据域的大小缩放图片
image.scaleToFit(signRect.getWidth(), signRect.getHeight());
// 添加图片
image.setAbsolutePosition(x, y);
under.addImage(image);
fos.flush();
fos.close();
/*stamper.close();*/
reader.close();
}
2:关键字签章,该方式是读取pdf里面的文字,以文字为中心进行定位。其实和上面差不多,只是定位方式变化了而已。
public static byte[] signPdfByStampKeyNocert(Object source, URL imagePath, String stampKey) throws Exception {
//source:待插入图片的pdf ,imagePath :待插入图片 , stampKey:关键字(比如 “图片插入在我这”)
// 临时文件路径
String targetPath = "E://source.pdf";
// 读取模板文件
PdfReader reader = null;
if(source instanceof String){
reader = new PdfReader((String)source);
}else if(source instanceof byte[]){
reader = new PdfReader((byte[])source);
}else if(source instanceof URL){
reader = new PdfReader((URL)source);
}
byte [] by1 = null;
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(targetPath));
// 则使用座标签章,获取关键字的各类参数 (这个方法我整合了,各位可自行查找)
Map<String, Object> params = PDFUtil.getSignaturePostionInfo(reader, imagePath, stampKey);
// 关键字
Rectangle signRect = (Rectangle) params.get("sign8PositionRectangle");
// 获取图片的绝对位置,距离
float x = signRect.getLeft();
float y = signRect.getBottom();
// 获取关键字所在页码
int pageno = (int) params.get("sign8PositionKeywordsPageIndex");
// 获取操作的页面
PdfContentByte overContent = stamper.getOverContent(pageno);
Image image = Image.getInstance(imagePath);
// 设置图片宽高
image.scaleToFit(signRect.getWidth(), signRect.getHeight());
// image.scaleAbsolute(x, y);
// 设置图片位置
image.setAbsolutePosition(x, y);// 左边距、底边距
overContent.addImage(image);
overContent.stroke();
stamper.close();
reader.close();
byte [] bytes = FileUtil.getFile(targetPath);
FileUtil.delFile(targetPath);
return bytes;
}