iText7:com.itextpdf.kernel.PdfException:文档已关闭。执行行动是不可能的

时间:2017-09-12 05:04:40

标签: java pdf itext itext7

我在iText7上遇到13:55:45.962 1 // (1) 13:55:47.252 2 // (1) 13:55:47.782 com.itextpdf.kernel.PdfException: Document was closed. It is impossible to execute action. at com.itextpdf.kernel.pdf.PdfDocument.checkClosingStatus(PdfDocument.java:1887) at com.itextpdf.kernel.pdf.PdfDocument.getWriter(PdfDocument.java:645) at com.itextpdf.kernel.pdf.PdfObject.makeIndirect(PdfObject.java:228) at com.itextpdf.kernel.pdf.PdfDictionary.makeIndirect(PdfDictionary.java:491) at com.itextpdf.kernel.pdf.PdfDictionary.makeIndirect(PdfDictionary.java:57) at com.itextpdf.kernel.pdf.PdfObject.makeIndirect(PdfObject.java:249) at com.itextpdf.kernel.pdf.PdfDictionary.makeIndirect(PdfDictionary.java:479) at com.itextpdf.kernel.pdf.PdfDictionary.makeIndirect(PdfDictionary.java:57) at com.itextpdf.kernel.font.PdfFont.makeObjectIndirect(PdfFont.java:600) at com.itextpdf.kernel.font.PdfType0Font.getFontDescriptor(PdfType0Font.java:672) at com.itextpdf.kernel.font.PdfType0Font.flushFontData(PdfType0Font.java:828) at com.itextpdf.kernel.font.PdfType0Font.flush(PdfType0Font.java:600) at com.itextpdf.kernel.pdf.PdfDocument.flushFonts(PdfDocument.java:1848) at com.itextpdf.kernel.pdf.PdfDocument.close(PdfDocument.java:800) at (our source (2) ) 错误。

	function split() {
	    var delimiter = "/";
	    var arr = [];
	    var highest = 0;
	    var columnIndex = "";
	    $('#tbl td:nth-child(3)').each(function() {
	        ColumnIndex = $(this).index();
	        var string = $(this).text();
	        var array = string.split(delimiter);
	        var nbrCharacter = (string.split(delimiter).length - 1) //COUNT OCCURENCES OF CHARACTER
	        var temp = (nbrCharacter > highest) ? highest++ : highest = highest;
	        arr.push(string.split(delimiter));
	    });
	    for (i = 0; i < highest; i++) { //ADD EMPTY COLUMNS
	        $('#tbl').find('tr').each(function() {
	            $(this).find('td').eq(ColumnIndex).after('<td></td>');
	        });
	    }
	    for (i = 0; i < arr.length; i++) { //POPULATE CELLS FROM ARRAY
	        var columnTracker = ColumnIndex
	        for (j = 0; j < arr[i].length; j++) {
	            $('#tbl').find('tr:eq(' + (i + 1) + ')').find('td:eq(' + columnTracker + ')').html(arr[i][j]);
	            columnTracker++
	        }
	    }
	}

我得到了这个输出。

th {
    height: 15px;
    min-width: 30px;
    border: 1px solid black;
    font-size: 12px;
    font-family: Courier, monospace;
    padding: 2px 5px 2px 5px;
}

td {
    height: 15px;
    min-width: 30px;
    border: 1px solid black;
    font-size: 12px;
    font-family: Courier, monospace;
    padding: 2px 5px 2px 5px;
}

为什么我收到此错误?我该如何解决?

[UPDATE] 我发现字体“MS Gothic”(日文Windows上的标准字体)的设置值导致此错误。似乎有些字体导致此错误,而其他字体则没有。我也试过HELVETICA,但它不会导致错误。我已经更新了我的程序(从第1行到第14行,第38行到第41行)。

1 个答案:

答案 0 :(得分:2)

我已经为你的代码制作了几乎文字的副本:

package com.itextpdf.samples;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import com.itextpdf.forms.PdfAcroForm;
import com.itextpdf.forms.PdfPageFormCopier;
import com.itextpdf.forms.fields.PdfFormField;
import com.itextpdf.io.font.FontProgram;
import com.itextpdf.io.font.FontProgramFactory;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.WriterProperties;

public class Test {

    public static void main(String[] args) throws IOException {
        FontProgram fontProgram = FontProgramFactory.createFont("c:/windows/fonts/msgothic.ttc,1");

        FileOutputStream outputStream = new FileOutputStream("test.pdf");
        WriterProperties wp = new WriterProperties();
        wp.useSmartMode();
        try (PdfDocument writeDoc = new PdfDocument(new PdfWriter(outputStream, wp))) {

            for (int keyNumber = 0; keyNumber < 3; keyNumber++) {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                try (PdfWriter writer = new PdfWriter(baos);
                    PdfDocument readDoc =
                        new PdfDocument(new PdfReader("form.pdf"), writer)) {
                    PdfAcroForm pdfAcroForm = PdfAcroForm.getAcroForm(readDoc, false);
                    Map<String, PdfFormField> fieldMap = pdfAcroForm.getFormFields();
                    if (fieldMap != null && fieldMap.size() > 0) {    
                        Set<String> fieldNameSet = new HashSet<>(fieldMap.keySet()); 
                        for (String fieldName : fieldNameSet) {
                            pdfAcroForm.renameField(fieldName, fieldName + "_" + keyNumber);
                        }
                        fieldMap = pdfAcroForm.getFormFields();
                    }

                    PdfFormField form = fieldMap.get("name_" + keyNumber);              
                    form.setFont(PdfFontFactory.createFont(fontProgram)).setValue("Test Test");
                }


                try (PdfDocument readDoc =
                    new PdfDocument(new PdfReader(new ByteArrayInputStream(baos.toByteArray())))) {
                    readDoc.copyPagesTo(1, readDoc.getNumberOfPages(), writeDoc, new PdfPageFormCopier());
                }
            }
        }
    }
}

运行时不会抛出任何错误。

我不得不做一些更改,因为我不知道keyList等参数是什么。你可以执行我的例子,并告诉我问题是否仍然存在?

  • 如果我的示例仍然出现错误:也许您没有使用最新版本的iText 7.请升级并重新尝试。
  • 如果我的示例没有抛出错误:尝试逐步调整我的示例,直到错误再次发生。告诉我们在错误发生之前您执行的最后一步是哪一步。

<强>更新

当您创建PdfFont并在PdfFont的上下文中使用该PdfDocument实例时,PdfFont“属于该文档,您可以不再重复使用它。您应该为每个文档创建一个新的PdfFont实例。这并不意味着您不能重复使用FontProgram

我已经更新了我的例子。我使用FontProgramFactory创建FontProgram(我使用了快速和简单的方法)。我不会重复使用任何PdfFont,但我会使用FontProgram为每个PdfFont创建一个新的PdfDocument