java: 关于pdf文件相关方法汇总

更新时间:2021-11-29
@[PDF]工具类涉及:1.添加水印 2.设置签名域 3.获取文件签名域信息

这里的方法基于com.itextpdf.text包
maven坐标:

<dependency>
      <groupId>com.itextpdf</groupId>
      <artifactId>itextpdf</artifactId>
      <version>5.5.13.2</version> 
 </dependency>

1.添加水印

 /**
   * 
   * @param filePath 需要添加水印的文件
   * @param waterMark 水印内容
   * @param outPath 输出文件路径
   * @throws Exception
   */
  public static void waterMarkAdd(String filePath,String waterMark,String outPath) throws Exception{
    byte[] bytes = getByteString(filePath);
    PdfReader reader = new PdfReader(bytes);
    PdfStamper stamper = new PdfStamper(reader,new FileOutputStream(outPath));
    BaseFont baseFont = BaseFont.createFont();
    Rectangle pageRect = null;
    PdfGState pdfGState = new PdfGState();
    pdfGState.setFillOpacity(0.3f);
    pdfGState.setStrokeOpacity(0.4f);
    int total = reader.getNumberOfPages()+1;
    JLabel label = new JLabel();
    FontMetrics fontMetrics;
    int textHeight = 0;
    int textWidth = 0;
    label.setText(waterMark);
    fontMetrics = label.getFontMetrics(label.getFont());
    textHeight = fontMetrics.getHeight();
    textWidth = fontMetrics.stringWidth(label.getText());
    PdfContentByte contentByte;
    int numJ = 0 ;
    int numK = 0 ;
    for(int i=1; i<total;i++){
      pageRect = reader.getPageSizeWithRotation(i);
      contentByte = stamper.getOverContent(i);
      contentByte.saveState();
      contentByte.setGState(pdfGState);
      contentByte.beginText();
      contentByte.setFontAndSize(baseFont,24);
      contentByte.setColorFill(BaseColor.BLACK);
      // 你可以随心所欲的改你自己想要的角度
				for (int height = textHeight; height < pageRect
						.getHeight(); height = height + textHeight * 5) {
					numJ ++ ;
					for (int width =  textWidth; width < pageRect
							.getWidth() + textWidth; width = width + textWidth * 3) {
						numK ++ ;
            // 设置水印文字成角度倾斜
						contentByte.showTextAligned(Element.ALIGN_LEFT,
								waterMark, width - textWidth, height - textWidth,
								35);

					}
				}

//      contentByte.showTextAligned(Element.ALIGN_LEFT,
//          waterMark, reader.getPageSize(i).getWidth()/2, reader.getPageSize(i).getHeight()/2,
//          45);

      // 添加水印文字
      contentByte.endText();
    }
    stamper.close();
    reader.close();
  }

/**
   * 文件转byte流
   * @param path 文件路径
   * @return 返回byte[]
   * @throws IOException
   */
  private static byte[] getByteString(String path) throws IOException {
    File file = new File(path);
    byte[] buf = new byte[1024];
    int len = 0;
    FileInputStream fis = new FileInputStream(file);
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    while((len = fis.read(buf))!=-1){
      bos.write(buf,0,len);
    }
    bos.flush();
    fis.close();
    bos.close();
    return bos.toByteArray();
  }

2.设置签名域

  public static byte[] setSignArea(byte[] tail,Map position, List posConfigSet) throws Exception {
    int xIndex = 0;
    int yIndex = 0;
    int yMax = 780;
    int yMin = 72;
    PdfReader reader = new PdfReader(tail);
    ByteArrayOutputStream baoPdfStream = new ByteArrayOutputStream();
    PdfStamper stamper = new PdfStamper(reader, baoPdfStream);
    // 创建数组签名域
    int width = 50, height = 50;
    int pageNo = position.getInt("PAGE_NUM");
    float x_pos = Float.parseFloat(position.getString("X_POS"))-xIndex;
    float y_pos = Float.parseFloat(position.getString("Y_POS"))-yIndex;
    y_pos = y_pos > yMax ? yMax : y_pos;
    y_pos = y_pos < yMin ? yMin : y_pos;
    Rectangle areaSignatureRect =
        new Rectangle(x_pos,y_pos,x_pos + width,y_pos + height);
    PdfFormField pdfFormField = PdfFormField.createSignature(stamper.getWriter());
    pdfFormField.setWidget(areaSignatureRect, PdfAnnotation.HIGHLIGHT_NONE);
    pdfFormField.setFieldName("signatureOne"); // 签名域标识
    pdfFormField.setPage(pageNo);
    stamper.addAnnotation(pdfFormField, pageNo);
    //必须关闭,否则创建的PDF为0KB
    stamper.close();
    return baoPdfStream.toByteArray();
  }

3.查看签名域信息

需要 com.spire.pdf 包

/**
   * 
   * @param filePath 文件路径
   * @return list 返回签名域信息集
   */
  public List<Map<String,String>> getSignature(String filePath) {
    List<Map<String,String>> list = new ArrayList<>();
    Map<String,String> result = new HashMap<>();
    //创建PdfDocument实例
    PdfDocument pdf = new PdfDocument();
    //加载含有签名的PDF文件
    pdf.loadFromFile(filePath);
    //获取域集合
    PdfFormWidget pdfFormWidget = (PdfFormWidget) pdf.getForm();
    PdfFormFieldWidgetCollection pdfFormFieldWidgetCollection = pdfFormWidget.getFieldsWidget();
    //遍历域
    for (int i = 0; i < pdfFormFieldWidgetCollection.getCount(); i++) {
    //判定是否为签名域
      if (pdfFormFieldWidgetCollection.get(i) instanceof PdfSignatureFieldWidget) {
      //获取签名域
        PdfSignatureFieldWidget signatureFieldWidget = (PdfSignatureFieldWidget) pdfFormFieldWidgetCollection
            .get(i);
        //获取签名
        PdfSignature signature = signatureFieldWidget.getSignature();
        String location = signature.getLocationInfo();
        String reason = signature.getReason();
        String data = signature.getDate().toString();
        String name = signature.getSignatureName();
        result.put("location",location);
        result.put("reason",reason);
        result.put("data",data);
        result.put("name",name);
        list.add(result);
        System.out.println(
            "location:" + location + ",reason:" + reason + ",data:" + data + ",name:" + name);
      }
    }
    return list;
  }

4 获取关键字位置坐标

//因匿名内部类原因定义为成员变量
  private int i = 0;
  /**
   * 获取关键字位置坐标
   * @param pdfIn pdf文件byte流
   * @param keyWord 关键字
   * @return 位置信息列表 [0]:x [1]:y [2]页数
   * @throws Exception
   */
  public List getPosition(byte[] pdfIn, String keyWord) throws Exception {
    List list = new ArrayList();
    PdfReader pdfReader = new PdfReader(pdfIn);
    int numberOfPages = pdfReader.getNumberOfPages();
    PdfReaderContentParser pdfReaderContentParser = new PdfReaderContentParser(pdfReader);
    for (i = 1; i <= numberOfPages; i++) {
      pdfReaderContentParser.processContent(i, new RenderListener() {
        @Override
        public void renderText(TextRenderInfo textRenderInfo) {
          String text = textRenderInfo.getText(); // 整页内容
          if (null != text && text.contains(keyWord)) {
            Float boundingRectange = textRenderInfo.getBaseline().getBoundingRectange();
            float[] arr = new float[3];
            arr[0] = boundingRectange.x;
            arr[1] = boundingRectange.y;
            arr[2] = i;
            list.add(arr);
          }
        }
        @Override
        public void renderImage(ImageRenderInfo arg0) {
        }
        @Override
        public void endTextBlock() {
        }
        @Override
        public void beginTextBlock() {
        }
      });
    }
    return list;
  }

5 签章签名填充日期换页时位置调整

/**
 *
 * @param pageSet 文件byte流
 * @param position 页数 x y
 * @return
 * @throws IOException
 * @throws DocumentException
 */
public static byte[] fillDate(byte[] pageSet,List<Float> position) throws IOException, DocumentException {
  //盖章日期填充偏移量 签名与日期同页偏移
  float y = -40f;
  float x = 0f;
  //判断是否翻页标志位
  float index = 73;
  File modelFile = new File(System.getProperty("user.dir"));
  if (!modelFile.exists()) {
    modelFile.mkdirs();
  }
  String nowDate = LocalDate.now().toString();
  PdfReader reader = new PdfReader(pageSet);
  FileOutputStream fos = new FileOutputStream(System.getProperty("user.dir") + "/" + nowDate + ".pdf");
  PdfStamper stamper = new PdfStamper(reader,fos);
  Integer pageNum = Integer.parseInt(position.get(2).toString());
  String xPos = position.get(0).toString();
  String yPos = position.get(1).toString();
  //签名与日期分页时特殊处理 ,如间距更大需继续特殊处理
  if (java.lang.Float.parseFloat(yPos) < index) {
    pageNum++;
    // 第一行:68 (729)第二行56  (711)第三行44(723)
    if(java.lang.Float.parseFloat(yPos)<74&& java.lang.Float.parseFloat(yPos)>60){
      y = 729;
    }else if(java.lang.Float.parseFloat(yPos)<60&& java.lang.Float.parseFloat(yPos)>52){
      y= 711;
    }else if (java.lang.Float.parseFloat(yPos)<48&& java.lang.Float.parseFloat(yPos)>40){
      y = 723;
    }
  }
  PdfContentByte pdfContentByte = stamper.getOverContent(pageNum);
  pdfContentByte.beginText();
  // 设置字体及字号
  pdfContentByte.setColorFill(BaseColor.DARK_GRAY);
  pdfContentByte.setFontAndSize(BaseFont.createFont(), 10);
  pdfContentByte.showTextAligned(Element.ALIGN_LEFT, nowDate,
      java.lang.Float.parseFloat(xPos) + x, y+ java.lang.Float.parseFloat(yPos), 0);
  pdfContentByte.endText();
  stamper.close();
  // 将输出流关闭
  fos.close();
  reader.close();
  File file = new File(System.getProperty("user.dir") + "/" + nowDate+ ".pdf");
  byte[] outputStream = FileCopyUtils.copyToByteArray(file);
  delFile(file);
  return outputStream;
}

public static void delFile(File file) {
  if (file.exists() && file.isFile()) {
    file.delete();
  }
}

6.PDF模板数据填充

pom依赖

   <dependency>
      <groupId>freemarker</groupId>
      <artifactId>freemarker</artifactId>
      <version>2.3.9</version>
    </dependency>
/**
   * 
   * @param param 填充参数
   * @param bytes 待文件文件流
   * @param fileName 文件名
   * @return
   * @throws Exception
   */
public static String processHtmlParam(Map param,byte[] bytes,String fileName) throws Exception {

    File modelFile = new File(System.getProperty("user.dir"));
    if (!modelFile.exists()) {
      modelFile.mkdirs();
    }

    FileOutputStream fos = null;
    try {
      fos = new FileOutputStream(System.getProperty("user.dir") + "/" + fileName);
      fos.write(bytes);
    }catch (Exception e) {
      System.out.println("文件写入失败 : " + e.getMessage());
    } finally {
      if ( null!=fos ) {
        fos.close();
      }
    }
    Configuration config = new Configuration();
    config .setDirectoryForTemplateLoading(modelFile);
    config .setObjectWrapper(new DefaultObjectWrapper());
    config .setDefaultEncoding("UTF-8");
    config .setClassicCompatible(true);

    Template template = config .getTemplate(fileName);

    StringWriter stringWriter = new StringWriter();
    BufferedWriter writer = new BufferedWriter(stringWriter);
    template.process(param, writer);
    String htmlStr = stringWriter.toString();

    writer.flush();
    writer.close();

    delFile(System.getProperty("user.dir"),fileName);

    return htmlStr;
  }

7.将字符串转换为PDF

 /**
   * 根据html字符串内容生成pdf
   *
   * @param pdfFilePath pdf文件存储位置
   * @param htmlcontent html内容
   */
  public static void parseHtml2PdfByString(String pdfFilePath, String htmlcontent) throws Exception{
    Document document = new Document();
    PdfWriter writer = null;
    try {
      writer = PdfWriter.getInstance(document, new FileOutputStream(pdfFilePath));
      // 设置底部距离60,解决重叠问题
      document.setPageSize(PageSize.A4);
      document.setMargins(50, 45, 50, 60);
      document.setMarginMirroring(false);
      document.open();
      XMLWorkerHelper.getInstance().parseXHtml(writer, document, new ByteArrayInputStream(htmlcontent.getBytes("UTF-8")), null, Charset
          .forName("UTF-8"), new MyFontProvider("C:\\Users\\rw\\Desktop\\ss.ttf"));
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if (null != document) {
        document.close();
      }
      if (null != writer) {
        writer.close();
      }
    }
  }

未完待续…

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值