使用iText的pdf交互式表格的外观问题

时间:2015-10-02 12:00:17

标签: java pdf pdf-generation itext

我一直在关注'第8章:填写互动表格' iText示例(http://itextpdf.com/examples/iia.php?id=154处的代码和pdf)并注意到一些与外观相关的问题,这些问题也在示例pdf中表现出来。

该示例包含单选按钮列表(圆圈内的经典点)和复选框列表(带红色背景的交叉框)。到现在为止还挺好。但是,以编程方式填充这些字段后生成的pdf在视觉上是不一致的。单选按钮全部恢复为正方形,所选的('西班牙语')在其中有一个翅膀(?)交叉而不是一个点。这些字段仍然可以编辑。当我选择其他单选按钮时,先前选择的单选按钮将恢复为空白圆圈。新选择的字段已从空方块更改为虚线圆圈。使用复选框也可以观察到这一点。

有没有办法填补田地,同时保留原貌?

谢谢!

编辑 - 这是我使用的代码的简化:

public void buildPdf() throws Exception {

    Document document = new Document(PageSize.A4);

    File file = new File("/test.pdf");
    final PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));

    document.open();

    PdfPCell cell = new PdfPCell();

    PdfRadioGroupTable group = new PdfRadioGroupTable("ndna", Arrays.asList("Not Available", "Not Applicable"), writer, Locale.ENGLISH, DEFAULT);

    cell.addElement(group);

    PdfPTable table = new PdfPTable(1);

    table.addCell(cell);

    cell = new PdfPCell();      

    cell.setCellEvent(new ActionEvent(writer, "http://localhost:8080/entrypointpdf"));

    table.addCell(cell);

    document.add(table);

    group.addAnnotations();

    document.close();
}

这里是ActionEvent

class ActionEvent implements PdfPCellEvent {

        private PdfWriter writer;
        private String submissionUrl;

        public ActionEvent(PdfWriter writer, String submissionUrl) {
            this.writer = writer;
            this.submissionUrl = submissionUrl;
        }

        @Override
        public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {

            PushbuttonField submit = new PushbuttonField(writer, position, "submit") {

                @Override
                public PdfFormField getField() throws IOException, DocumentException {

                    PdfFormField field = super.getField();

                    field.setAction(PdfAction.createSubmitForm(submissionUrl, null, 0));

                    return field;
                }
            };
            submit.setText("CLICK ME");
            submit.setTextColor(BaseColor.BLUE);
            submit.setFont(DEFAULT.getCalculatedBaseFont(false));
            submit.setVisibility(PushbuttonField.VISIBLE);

            try {
                writer.addAnnotation(submit.getField());
            } catch (Exception ignore) {
            }
        }
    }

这是PdfRadioGroupTable

public class PdfRadioGroupTable extends PdfPTable {

    private PdfWriter writer;
    public PdfFormField radioGroup;

    public PdfRadioGroupTable(String name, List<String> choices, PdfWriter writer, Locale locale, Font font) {
        super(2);

        this.writer = writer;

        setWidthPercentage(100);
        try {
            setTotalWidth(new float[] { 14, 400 });
        } catch (DocumentException ignore) {
        }

        radioGroup = PdfFormField.createRadioButton(writer, true);
        radioGroup.setFieldName(name);

        PdfPCell cell;

        for (String choice : choices) {
            cell = new PdfPCell();

            cell.setBorder(0);
            cell.setPaddingBottom(5);

            cell.setUseAscender(true);
            cell.setUseDescender(true);
            cell.setVerticalAlignment(PdfPCell.ALIGN_CENTER);

            cell.setCellEvent(new RadioCellEvent(radioGroup, choice));

            addCell(cell);

            cell = new PdfPCell();

            cell.setBorder(0);

            cell.setPaddingBottom(5);
            cell.setPaddingLeft(6);

            cell.setUseAscender(true);
            cell.setUseDescender(true);
            cell.setVerticalAlignment(PdfPCell.ALIGN_CENTER);

            cell.addElement(new Phrase(choice), font));

            addCell(cell);
        }
    }

    class RadioCellEvent implements PdfPCellEvent {

        protected PdfFormField radioGroup;
        protected String value;

        public RadioCellEvent(PdfFormField radioGroup, String value) {
            this.radioGroup = radioGroup;
            this.value = value;
        }

        @Override
        public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {

            RadioCheckField radio = new RadioCheckField(writer, position, null, value);

            radio.setChecked(false);

            radio.setBorderColor(GrayColor.GRAYBLACK);
            radio.setBackgroundColor(GrayColor.GRAYWHITE);
            radio.setCheckType(RadioCheckField.TYPE_CIRCLE);

            try {
                PdfFormField field = radio.getRadioField();

                writer.addAnnotation(field);
                radioGroup.addKid(field);

            } catch (Exception exception) {
                throw new ExceptionConverter(exception);
            }
        }
    }
}   

当点击pdf中的按钮(在acrobat中)时,服务器端会发生什么:

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException {

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        response.setContentType("application/pdf");
        response.setHeader("Content-Disposition", "inline; filename=\"your.pdf\"");

        try {
            FdfReader fdf = new FdfReader(request.getInputStream());

            File pdfFile = new File("/test.pdf");

            InputStream is = new FileInputStream(pdfFile);

            PdfReader reader = new PdfReader(is);

            File resultFile = new File(System.currentTimeMillis() + "_" + pdfFile.getName());
            FileOutputStream out = new FileOutputStream(resultFile);

            PdfStamper stamper = new PdfStamper(reader, out);

            AcroFields fields = stamper.getAcroFields();
            fields.setFields(fdf);

            // EXTRACT VALUES HERE                                  

            stamper.setFormFlattening(true);

            stamper.close();
            reader.close();

            ByteArrayOutputStream bos = new ByteArrayOutputStream();

            bos.write(FilesUtilities.read(resultFile));

            OutputStream os = response.getOutputStream();
            bos.writeTo(os);
            os.flush();

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

所以基本上我用一个radiogroup和一个按钮生成一个pdf。该按钮导致导入pdf字段,其目的是发送一个&#39;收据&#39;以先前生成的pdf形式返回给用户,其中包含与用户选择/值和导入状态字段相同的字段(ok,missing,bad data等)(我在上面的代码中省略了该部分的工作原理)精细)。我的问题是,返回的pdf中的无线电字段看起来并不像原始pdf中的可编辑的那样(它们甚至看起来都不像单选按钮)。

Before

Returned

我尝试使用

fields.setFieldProperty("ndna", "setfflags", PdfFormField.FF_READ_ONLY, null);

并且通过这种方式禁用表单展平会导致返回的pdf中出现相同的替换外观。

我的帮助将非常受欢迎,因为我现在已经挣扎了一段时间......

安东尼

1 个答案:

答案 0 :(得分:0)

这似乎是某些版本iText的错误。 iTextSharp版本5.5.5我遇到了同样的问题,升级到版本5.5.9后它就解决了。我用“nuget”来做这件事。这是一个链接:https://www.nuget.org/packages/iTextSharp/5.5.9