需求
客户希望在 PDF 文件上,借助手写板完成签名操作,其中手写板是个可以把签名转成图片的的硬件,硬件部分由于来源繁多,此处略过,默认已经拿到图片签名。
解决方案一
问题的本质是需要在 PDF 文件上,在指定的坐标位置或者提前定义的关键字处,插入图片,可以使用 Aspose.PDF for Java 来实现。实现的代码如下:
- model层
@Data
@ApiModel("pdf插入图片入参")
public class AddImageInPdfModel implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "待处理的pdf文件地址")
private String pdfFilePath;
@ApiModelProperty(value = "插入的base64图片")
private String base64Pic;
@ApiModelProperty(value = "第几页需要插入图片")
private int pageNum;
@ApiModelProperty(value = "底部x坐标")
private float lowerLeftX;
@ApiModelProperty(value = "底部y坐标")
private float lowerLeftY;
@ApiModelProperty(value = "第几个关键字位置需要插入图片", hidden = true)
private int keywordNum;
@ApiModelProperty(value = "关键字")
private String keyword;
@ApiModelProperty(value = "关键字位置:1-顺数 2-倒数", hidden = true)
private int keywordType;
}
- controller层
@PostMapping("/addImageInPdf")
@ApiOperation(value = "pdf插入图片", notes = "pdf插入图片")
public ResultBean<String> addImageInPdf(@ApiParam(value = "pdf插入图片入参", required = true)@RequestBody AddImageInPdfModel addImageInPdfModel) {
try {
log.info("pdf插入图片入参:{}", addImageInPdfModel);
String newPdfFilePath = pdfConvertService.addImageInPdf(addImageInPdfModel);
return ResultBean.ok(newPdfFilePath);
}catch (Exception e) {
log.error("pdf插入图片失败:{}", e.getMessage(), e);
return ResultBean.fail("pdf插入图片失败:" + e.getMessage());
}
}
- service层
import com.aspose.pdf.TextFragment;
import com.aspose.pdf.TextFragmentAbsorber;
import com.aspose.pdf.TextFragmentCollection;
import com.aspose.pdf.facades.PdfFileMend;
......
public String addImageInPdf(AddImageInPdfModel addImageInPdfModel) throws Exception {
String pdfFilePath = addImageInPdfModel.getPdfFilePath();
PdfFileMend mender = new PdfFileMend();
mender.bindPdf(pdfFilePath);
// 将图片写到磁盘
String imgDir = FileConfigConstant.ROOT_PATH + "writSign" + File.separator + "picture" + AttachmentUtil.createUploadFileSavePath();
Files.createDirectories(Paths.get(imgDir));
String imgName = IdUtil.simpleUUID() + ".png";
String imgPath = FilePathUtil.joinPath(imgDir, imgName);
log.info("pdf插入的图片地址:{}", imgPath);
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(imgPath));
BufferedImage bufferedImage = ImgUtil.toImage(addImageInPdfModel.getBase64Pic());
float picHeight = bufferedImage.getHeight();
float picWidth = bufferedImage.getWidth();
log.info("图片高度:{}", picHeight);
log.info("图片宽度:{}", picWidth);
boolean pic = ImageIO.write(bufferedImage, "png", new File(imgPath));
if(pic == false){
log.info("转换失败");
}
String keyword = addImageInPdfModel.getKeyword();
if (StringUtils.isNotBlank(keyword)){
//关键字签章
if (NumConstant.INT_ZERO == addImageInPdfModel.getKeywordNum()){
List<float[]> positions = PdfKeywordFinder.findKeywordPostions(pdfFilePath, keyword);
if (positions != null && positions.size() > 0) {
for (float[] position : positions) {
System.out.print("pageNum: " + (int) position[0]);
System.out.print("\tx:" + position[1]);
System.out.println("\ty: " + position[2]);
int pageNum = (int)position[0];
float lowerLeftX = position[1];
float lowerLeftY = position[2];
float upperRightX = lowerLeftX + picWidth;
float upperRightY = lowerLeftY + picHeight;
mender.addImage(imgPath, pageNum, lowerLeftX, lowerLeftY, upperRightX, upperRightY);
}
}
}else {
float[] positions = PdfKeywordFinder.getAddImagePositionXY(pdfFilePath, keyword, addImageInPdfModel.getKeywordNum(), addImageInPdfModel.getKeywordType());
int pageNum = (int)positions[0];
float lowerLeftX = positions[1];
float lowerLeftY = positions[2];
float upperRightX = lowerLeftX + picWidth;
float upperRightY = lowerLeftY + picHeight;
log.info("插入图片的位置,lowerLeftX:{},lowerLeftY:{},upperRightX:{},upperRightY:{}", lowerLeftX, lowerLeftY, upperRightX, upperRightY);
mender.addImage(imgPath, pageNum, lowerLeftX, lowerLeftY, upperRightX, upperRightY);
}
}else {
//位置签章
float lowerLeftX = addImageInPdfModel.getLowerLeftX();
float lowerLeftY = addImageInPdfModel.getLowerLeftY();
float upperRightX = lowerLeftX + picWidth;
float upperRightY = lowerLeftY + picHeight;
log.info("插入图片的位置,lowerLeftX:{},lowerLeftY:{},upperRightX:{},upperRightY:{}", lowerLeftX, lowerLeftY, upperRightX, upperRightY);
mender.addImage(imgPath, addImageInPdfModel.getPageNum(), lowerLeftX, lowerLeftY, upperRightX, upperRightY);
}
//构造新的pdf文件路径
String newPdfFilePath = pdfFilePath.replace(FileUtil.mainName(pdfFilePath), IdUtil.simpleUUID() + "_publicSign-" + DateUtil.currentSeconds());
log.info("签名后的pdf文件路径:{}", newPdfFilePath);
mender.save(newPdfFilePath);
out.close();
mender.close();
return newPdfFilePath;
}
解决方案二
也可以使用 itext 库对 PDF 进行关键字签名操作,参考地址如下:
使用itext对pdf指定文字位置插入图片