当前位置: 首页 > 知识库问答 >
问题:

PDFBOX 2.0+java flatten annotations freetext由foxit创建

隆康平
2023-03-14

我遇到了一个非常棘手的问题。我们有一些本来应该填写的html" target="_blank">表单,但有些人在foxit中使用了注释自由格式文本注释,而不是填写表单字段,所以注释永远不会变平。当我们的渲染软件生成最终文档时,注释并不包括在内。

我尝试的解决方案是,基本上遍历文档,获取注释文本内容,并将其写入pdf,这样它就在最终文档上,然后删除实际的注释,但我遇到了一个问题,我不知道注释使用的字体、行空间等,因此无法找到如何从pdfbox获取它,以便在未展平的表单上精确地重新创建注释。基本上,我想要扁平化在foxit(打字机注释功能)中创建的自由形式的注释,这里是代码。它是工作的,但再次我挣扎于弄清楚如何得到注释写到我的最终pdf文档。再一次,压扁在顶形是不起作用的,因为这些不是顶形场!活动代码过滤掉任何不是freetext类型注释的内容,但下面的代码应该显示我的问题。

    public static void main(String [] args)
{
        String startDoc = "C:/test2/test.pdf";
     String  finalFlat = "C:/test2/test_FLAT.pdf";

    try {
        // for testing
        try {
            //BasicConfigurator.configure();
            File myFile = new File(startDoc);
            PDDocument pdDoc = PDDocument.load( myFile );
            PDDocumentCatalog pdCatalog = pdDoc.getDocumentCatalog();
            PDAcroForm pdAcroForm = pdCatalog.getAcroForm();

            // set the NeedApperances flag
            pdAcroForm.setNeedAppearances(false);

            // correct the missing page link for the annotations
            for (PDPage page : pdDoc.getPages()) {

                for (PDAnnotation annot : page.getAnnotations()) {
                    System.out.println(annot.getContents());
                    System.out.println(annot.isPrinted());
                    System.out.println(annot.isLocked());

                    System.out.println(annot.getAppearance().toString());
                    PDPageContentStream contentStream = new PDPageContentStream(pdDoc, page, PDPageContentStream.AppendMode.APPEND,true,true);
                    int fontHeight = 14; 
                    contentStream.setFont(PDType1Font.TIMES_ROMAN, fontHeight);

                    float height = annot.getRectangle().getLowerLeftY();

                    String s  = annot.getContents().replaceAll("\t", "    ");

                    String ss[] = s.split("\\r");
                    for(String sss : ss)
                    {
                        contentStream.beginText();  
                        contentStream.newLineAtOffset(annot.getRectangle().getLowerLeftX(),height );
                      contentStream.showText(sss);
                      height = height + fontHeight * 2 ;

                      contentStream.endText();
                    }
                      contentStream.close();
                    page.getAnnotations().remove(annot);                    
                }
            }               
            pdAcroForm.flatten();
            pdDoc.save(finalFlat);
            pdDoc.close();
        }
        catch (Exception e) {
            e.printStackTrace();
        }   

    }
    catch (Exception e) {
        System.err.println("Exception: " + e.getLocalizedMessage());
    }
}

共有1个答案

顾超
2023-03-14

这不是一个有趣的。经过一百万次不同的测试,我仍然不理解所有的细微差别,但这是一个版本,呼吁扁平所有pdf文件和注解,如果他们在pdf上可见。测试了大约六个pdf Creator,如果一个注释在页面上是可见的,这有望使它扁平化。我怀疑有一个更好的方法,通过拉矩阵,并转换它和其他什么,但这是唯一的方法,我让它工作在任何地方。

public static void flattenv3(String startDoc, String endDoc) {

  org.apache.log4j.Logger.getRootLogger().setLevel(org.apache.log4j.Level.INFO);
  String finalFlat = endDoc;


  try {

   try {
    //BasicConfigurator.configure();
    File myFile = new File(startDoc);
    PDDocument pdDoc = PDDocument.load(myFile);
    PDDocumentCatalog pdCatalog = pdDoc.getDocumentCatalog();
    PDAcroForm pdAcroForm = pdCatalog.getAcroForm();

    if (pdAcroForm != null) {
     pdAcroForm.setNeedAppearances(false);
     pdAcroForm.flatten();
    }

    // set the NeedApperances flag

    boolean isContentStreamWrapped;
    int ii = 0;

    for (PDPage page: pdDoc.getPages()) {
     PDPageContentStream contentStream;
     isContentStreamWrapped = false;
     List < PDAnnotation > annotations = new ArrayList < > ();

     for (PDAnnotation annotation: page.getAnnotations()) {



      if (!annotation.isInvisible() && !annotation.isHidden() && annotation.getNormalAppearanceStream() != null)

      {
       ii++;
       if (ii > 1) {
        // contentStream.close();
        // continue;

       }


       if (!isContentStreamWrapped) {
        contentStream = new PDPageContentStream(pdDoc, page, AppendMode.APPEND, true, true);
        isContentStreamWrapped = true;
       } else {
        contentStream = new PDPageContentStream(pdDoc, page, AppendMode.APPEND, true);
       }

       PDAppearanceStream appearanceStream = annotation.getNormalAppearanceStream();

       PDFormXObject fieldObject = new PDFormXObject(appearanceStream.getCOSObject());

       contentStream.saveGraphicsState();


       boolean needsTranslation = resolveNeedsTranslation(appearanceStream);



       Matrix transformationMatrix = new Matrix();
       boolean transformed = false;

        float lowerLeftX = annotation.getNormalAppearanceStream().getBBox().getLowerLeftX();
        float lowerLeftY = annotation.getNormalAppearanceStream().getBBox().getLowerLeftY();
        PDRectangle bbox = appearanceStream.getBBox();
        PDRectangle fieldRect = annotation.getRectangle();

        float xScale = fieldRect.getWidth() - bbox.getWidth();

        transformed = true;

        lowerLeftX = fieldRect.getLowerLeftX();
        lowerLeftY = fieldRect.getLowerLeftY();
        if (bbox.getLowerLeftX() <= 0 && bbox.getLowerLeftY() < 0 && Math.abs(xScale) < 1) //BASICALLY EQUAL TO 0 WITH ROUNDING
        {


         lowerLeftY = fieldRect.getLowerLeftY() - bbox.getLowerLeftY();
         if (bbox.getLowerLeftX() < 0 && bbox.getLowerLeftY() < 0) //THis is for the o
         {

          lowerLeftX = lowerLeftX - bbox.getLowerLeftX(); 

         }

        } else if (bbox.getLowerLeftX() == 0 && bbox.getLowerLeftY() < 0 && xScale >= 0) {

         lowerLeftX = fieldRect.getUpperRightX();

        } else if (bbox.getLowerLeftY() <= 0 && xScale >= 0) {

         lowerLeftY = fieldRect.getLowerLeftY() - bbox.getLowerLeftY() - xScale;

        } else if (bbox.getUpperRightY() <= 0) {

         if (annotation.getNormalAppearanceStream().getMatrix().getShearY() < 0) {
          lowerLeftY = fieldRect.getUpperRightY();
          lowerLeftX = fieldRect.getUpperRightX();

         }

        } else {

        }



        transformationMatrix.translate(lowerLeftX,
         lowerLeftY);
        contentStream.transform(transformationMatrix);


       contentStream.drawForm(fieldObject);
       contentStream.restoreGraphicsState();
       contentStream.close();
      }
     }
     page.setAnnotations(annotations);
    }


    pdDoc.save(finalFlat);
    pdDoc.close();
    File file = new File(finalFlat);

    // Desktop.getDesktop().browse(file.toURI());


   } catch (Exception e) {
    e.printStackTrace();
   }

  } catch (Exception e) {
   System.err.println("Exception: " + e.getLocalizedMessage());
  }
 }

}

 类似资料:
  • Foxit Reader(福昕阅读器)是一个小巧的 PDF 文档阅读器,完全免费(非开源软件)。有了它,你无须为仅仅阅读PDF文档而下载和安装庞大的Adobe Reader,而且启动快速,无需安装。对中文支持非常好。 全新的Ribbon界面; 支持PDF文档手写签名、插入印章; 更多安全控制包括Foxit DRM内容管理插件; 支持微软AD RMS对PDF文档的安全应用

  • Foxit PDF Creator是一款虚拟打印机(非开源软件,可免费使用),通过这款虚拟打印机任何支持打印的应用程序可以非常方便、高效地创建生成高品质的PDF文档。和备受大家欢迎的 Foxit Reader一样,Foxit PDF Creator也是基于Foxit同一核心技术研发并设计出来的。 此工具具备有强大的 搜索功能和高效的PDF显示及处理能力,本身体积小巧,运行快速并且 显示精确,可以将

  • 在pdf文件中,在按钮后面的代码中,我有 exit命令在Phantom PDF(旧版本,2.2)中运行良好,但在Foxit Reader(8.3,相当新的版本)中运行不好。那里什么也没有发生。 我还检查了一个旧的Foxit阅读器版本3.3,它在那里按预期工作。 我尝试了“安全性”和“信任管理器”设置,但这些设置并没有改善这种情况。 我想在按下按钮时关闭读卡器。

  • Blade 中注册路由有 2 种方式,一种是使用 Blade 对象硬编码注册,另一种是通过控制器来管理多个路由。 在前面的 main 函数中我们使用第一种方式注册了一个路由。 上面的写法看起来是很简洁的,也用到java8的语法,但是一般我们编写一个站点的时候会有很多的路由,都放在一个文件中不是很好管理,这时候 Blade 支持你沿用 SpringMvc 的编程习惯,我们可以编写一个控制器,在你的

  • 如果你只需要掌控一个应用的全部的消息和触发的事件,那么使用默认的**/**命名空间即可。如果你想要利用第三方代码,或者分享你的代码给别人,http://socket.io提供了一种命名一个socket的途径。 使用多路由控制一条单一的连接是有好处的。比如下方的示例代码,客户端发起两个WebSocket连接,而服务器端使用多路由技术仅仅只需要建立一个连接。 服务器端(app.js) var io =