java - iText - Java Android - 将字段添加到现有 pdf

标签 java android pdf itext

我正在尝试向现有 PDF 添加交互式字段,我使用 PdfReader 和 PdfStamper 来执行此操作,当我在平板电脑上打开它时,一切正常。但是,当我想在我的计算机上打开它时,没有任何字段。

这是我的代码示例,每一页都有多个字段,但我在这里只打印了两个字段:

public class SelfNoteFragment extends Fragment {
    private PdfStamper pdfStamper;

    class MyCellField implements PdfPCellEvent {
        protected String fieldname;
        protected int page;
        public MyCellField(String fieldname, int page) {
            this.fieldname = fieldname;
            this.page = page;
        }
        public void cellLayout(PdfPCell cell, Rectangle rectangle, PdfContentByte[] canvases) {
            final PdfWriter writer = canvases[0].getPdfWriter();
            final TextField textField = new TextField(writer, rectangle, fieldname);
            try {
                final PdfFormField field = textField.getTextField();
                pdfStamper.addAnnotation(field, page);
            } catch (final IOException ioe) {
                throw new ExceptionConverter(ioe);
            } catch (final DocumentException de) {
                throw new ExceptionConverter(de);
            }
        }
    }

    class CheckboxCellEvent implements PdfPCellEvent {
        protected String name;
        protected boolean check;
        protected int page;

        public CheckboxCellEvent(String name, boolean check, int page) {
            this.check = check;
            this.name = name;
            this.page = page;
        }

        public void cellLayout(PdfPCell cell, Rectangle position,
                               PdfContentByte[] canvases) {
            PdfWriter writer = canvases[0].getPdfWriter();
            float x = position.getLeft();
            float y = position.getBottom();
            Rectangle rect = new Rectangle(x-5, y-5, x+5, y+5);
            RadioCheckField checkbox = new RadioCheckField(
                    writer, rect, name, "Yes");
            checkbox.setCheckType(RadioCheckField.TYPE_CROSS);
            checkbox.setChecked(check);
            try {
                pdfStamper.addAnnotation(checkbox.getCheckField(), page);
            } catch (Exception e) {
                throw new ExceptionConverter(e);
            }
        }
    }

    private void createPdf(int idPrevision) throws FileNotFoundException, DocumentException {

        try {
            PdfReader pdfReader = new PdfReader("/storage/emulated/0/Documents/fiche_chantier2.pdf");

            //Create time stamp
            Date date = new Date() ;
            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(date);

            File pdfFolder = new File(Environment.getExternalStoragePublicDirectory(
                    Environment.DIRECTORY_DOCUMENTS), "Prevision_");
            if (!pdfFolder.exists()) {
                pdfFolder.mkdir();
            }

            File myFile = new File(pdfFolder + timeStamp + ".pdf");

            OutputStream output = new FileOutputStream(myFile);

            this.pdfStamper = new PdfStamper(pdfReader, output);

            PdfContentByte canvas1;
            PdfContentByte canvas2;

            canvas1 = pdfStamper.getOverContent(1);
            canvas2 = pdfStamper.getOverContent(2);

            PdfPCell cellFillFieldPage1 = new PdfPCell();
            cellFillFieldPage1.setCellEvent(new MyCellField("", 1));
            cellFillFieldPage1.setFixedHeight(15);
            cellFillFieldPage1.setBorder(Rectangle.NO_BORDER);
            cellFillFieldPage1.setVerticalAlignment(Element.ALIGN_MIDDLE);

            PdfPCell cellCheckBoxPage2 = new PdfPCell();
            cellCheckBoxPage2.setCellEvent(new CheckboxCellEvent("", false, 2));
            cellCheckBoxPage2.setBorder(Rectangle.NO_BORDER);

            // ************** PAGE 1 ************** //

            // SET TABLE
            PdfPTable tableSection1Page1 = new PdfPTable(1);
            tableSection1Page1.setTotalWidth(136);
            tableSection1Page1.setWidthPercentage(100.0f);
            tableSection1Page1.setLockedWidth(true);

            // ADD CELLS TO TABLE
            tableSection1Page1.addCell(cellFillFieldPage1);


            // PRINT TABLES
            tableSection1Page1.writeSelectedRows(0, -1, 165, 730, canvas1);


            // ************ PAGE 2 ************ //

            // SET TABLES
            PdfPTable tableSection1Page2 = new PdfPTable(1);
            tableSection1Page2.setTotalWidth(10);
            tableSection1Page2.setWidthPercentage(100.0f);
            tableSection1Page2.setLockedWidth(true);

            // ADD CELLS TO TABLE
            tableSection1Page2.addCell(cellCheckBoxPage2);

            // PRINT TABLES
            tableSection1Page2.writeSelectedRows(0, -1, 182, 736, canvas2);

            // I tried this, but it didn't change anything
            pdfStamper.setFormFlattening(false);

            pdfStamper.close();
            pdfReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
     }
}

您知道为什么我创建的 PDF 在我的平板电脑上很好,但在我的计算机上却不好(当我想通过邮件发送它时也是如此)?如果是这样,您知道如何解决这个问题吗?

谢谢你, 科朗坦

最佳答案

您的代码实际上有两个问题,

  1. 您创建名称为空的字段:

    cellFillFieldPage1.setCellEvent(new MyCellField("", 1));
    ...
    cellCheckBoxPage2.setCellEvent(new CheckboxCellEvent("", false, 2));
    

    首先,字段需要有一个名称。此外,即使允许选择空名称,两个具有相同名称的字段也会被视为同一抽象字段的两种表示形式,如果一个是文本字段而另一个是复选框字段,则很难实现这一点。

    一旦您使用非空的不同名称命名这些字段,您就会在 Adob​​e Reader DC/Win 上看到您的字段:您可以使用 TAB 键切换这些字段并更改它们的值。但不幸的是,它们是无国界的,因此,如果是空的,就很难被发现。这是因为

  2. 您没有为字段设置边框颜色。因此,iText 创建无边框的表单字段外观流。

    您可以像这样设置边框颜色:

    ...
    final TextField textField = new TextField(writer, rectangle, fieldname);
    textField.setBorderColor(BaseColor.BLACK);
    ...
    RadioCheckField checkbox = new RadioCheckField(writer, rect, name, "Yes");
    checkbox.setBorderColor(BaseColor.BLACK);
    ...
    

    完成后,您会得到带有黑色边框的字段...

<小时/>

如果您想知道为什么不同的观看者(即使是同一家公司的同名观众)在这里表现不同......

  1. 一些 PDF 查看器很早就意识到他们无法正确处理名称为空的字段,因此甚至不显示它们,而其他查看器稍后在尝试保存或发布表单时才意识到这一点,或者根本无法识别它,从而产生损坏的输出。

  2. PDF 查看器可以忽略表单字段的外观流(实际上是一般注释)并创建自己的外观;因此,在当前的情况下,他们可能会忽略 iText 生成的无边框外观并绘制具有可见边框的外观。

关于java - iText - Java Android - 将字段添加到现有 pdf,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35630320/

相关文章:

css - z-index 在 Internet Explorer 中无法使用 iframe 中的 pdf

pdf - 强制 PDF 显示内联,即使 Content-Disposition 另有说明?

java - NeighboringCellInfo、CID 和 LAC 的空问题

firefox - Selenium 可以验证浏览器加载的 PDF 中的文本吗?

java - Android光标越界异常索引0

Java:对象的哈希函数

java - 将友谊保存在数据库中。社交网络服务

java - 父类(super class)型没有实现和覆盖

java - 正在寻找一个真正好的地方来学习一些直接的 Java 和 'abstract' 概念来帮助 Android!完整的Java初学者:)

安卓SDK : Show one line at a time and proceed with onClick