iText-ExceptionConverter:java.io.IOException:流关闭

时间:2018-07-12 11:31:31

标签: java exception stream itext

我正在尝试调整pdf文档的大小,然后在每页中放置一个图章。

我正在使用“文档”调整大小,并使用“ PdfStamper”作为图章。

PdfStamper stamp = new PdfStamper(reader, output);
Document document = new Document();

问题是当我关闭两次时:document.close()和stamp.close() 我收到 ExceptionConverter:java.io.IOException:流已关闭

我知道这是因为我同时关闭了文档和图章,但是如果我只关闭了一个,则仅关闭对象即可。

我不知道该如何处理。

有什么想法吗? 谢谢!

编辑-这是我现在拥有的所有代码:

public void generateReducedPdf() throws Exception {

    //lectura del pdf a copiar
    PdfReader reader = new PdfReader("C:/Users/X30261GE/Downloads/ES_O00012741_2018_000000000000000000000000000153.pdf");
    int numberOfPages = reader.getNumberOfPages();

    Document document = new Document();

    //creación del nuevo pdf, junto con su ruta y nombre.

    FileOutputStream output = new FileOutputStream("C:/Users/X30261GE/Downloads/pdfReducido.pdf");
    PdfWriter writer = PdfWriter.getInstance(document,  output);

    //PDF TIPO PDF/A1-b
    writer.setPDFXConformance(com.lowagie.text.pdf.PdfWriter.PDFA1B);

    document.open();
    document.setPageSize(PageSize.A4);

    PdfDictionary outi = new PdfDictionary(PdfName.OUTPUTINTENT);
    outi.put(PdfName.OUTPUTCONDITIONIDENTIFIER, new PdfString("sRGB IEC61966-2.1"));
    outi.put(PdfName.INFO, new PdfString("sRGB IEC61966-2.1"));
    outi.put(PdfName.S, PdfName.GTS_PDFA1);

    InputStream inst = ActionSignPdf.class.getClassLoader().getResourceAsStream("resources/sRGB.profile");          
    com.itextpdf.text.pdf.ICC_Profile icc = ICC_Profile.getInstance(inst);

    PdfICCBased ib = new PdfICCBased(icc);
    ib.remove(PdfName.ALTERNATE);
    outi.put(PdfName.DESTOUTPUTPROFILE, writer.addToBody(ib).getIndirectReference());
    writer.getExtraCatalog().put(PdfName.OUTPUTINTENTS, new PdfArray(outi));

    PdfContentByte pdfContent = writer.getDirectContent();



    for (int i = 1; i <= numberOfPages; i++) {

        document.newPage();
        PdfImportedPage page = writer.getImportedPage(reader, i);
        // Reducir las paginas al 80%
        pdfContent.addTemplate(page, .85f, 0, 0, .85f, 70, 110);



    }

    writer.createXmpMetadata();
    document.close();
    writer.close();


    //AHORA StAMP time
    //PRUEBA DE STAMP AQUI
    PdfStamper stamp = new PdfStamper(reader, output);
    PdfContentByte over;
    FontFactory.defaultEmbedding = true;
    FontFactory.register(ActionSignPdf.class.getResource("").getPath() + "Helvetica.ttf", ActionSignPdf.class.getResource("").getPath() + "Helvetica.ttf"); 
    BaseFont bf = BaseFont.createFont(ActionSignPdf.class.getResource("").getPath() + "Helvetica.ttf", BaseFont.WINANSI, BaseFont.EMBEDDED);
    BaseFont bfNegrita = BaseFont.createFont(BaseFont.TIMES_BOLD, BaseFont.WINANSI, BaseFont.EMBEDDED);


    // mete el for
    for (int i = 1; i <= numberOfPages; i++) {
    //PRUEBA DEL StAMP AQUI

        over = stamp.getOverContent(i);
        over.beginText();

        //set fuente negrita
        over.setFontAndSize(bfNegrita,8);

        //Primera linea
        //Coloco la primera parte en negrita
        int posLineaXNegrita = 150;

        over.showTextAligned(0, RegistroKeys.KEY_DIRECCION , posLineaXNegrita, 50, 0);
        //segunda parte

        //set fuente sin negrita
        over.setFontAndSize(bf,7);
        //posicion x donde colocare la segunda parte sin negrita

        int posLineaX = RegistroKeys.KEY_DIRECCION.length() + posLineaXNegrita + 108;
        over.setLineWidth(0);
        over.showTextAligned(0, RegistroKeys.KEY_DIRECCION_URL , posLineaX, 50, 0);

        //Siguiente linea
        //set fuente negrita
        over.setFontAndSize(bfNegrita,8);
        //primera parte en negrita
        posLineaXNegrita = 200;

        over.showTextAligned(Element.ALIGN_CENTER, RegistroKeys.KEY_CODIGO_SEGURO_DESCARGA, posLineaXNegrita, 40, 0);

        //segunda parte
        //set fuente sin negrita
        over.setFontAndSize(bf,7);
        //posicion x donde colocare la segunda parte sin negrita
        posLineaX = RegistroKeys.KEY_CODIGO_SEGURO_DESCARGA.length() + posLineaXNegrita + 105;
        String codigo =  "#002#9B4ECE66-A34D-3C0A-A6FA-6D67C31C9550";
        over.showTextAligned(Element.ALIGN_CENTER, codigo, posLineaX, 40, 0);
        over.endText();                 
        over.stroke(); 
    }
    stamp.close();
}

就像您在评论中说的那样,我正在尝试在同一PDF中使用图章和文档,但这将无法正常工作。

我必须先处理文档,然后再处理压模。 有任何想法吗?谢谢!

1 个答案:

答案 0 :(得分:0)

实际问题

在评论中发现,实际问题是

  

我认为我首先要处理文档,然后使用该结果来使用Stamper。现在我的问题是,该怎么做,如何从文档生成的输出中获取字节数组。

您可以通过将Document / PdfWriter对写到ByteArrayOutputStream来实现:

ByteArrayOutputStream baos = new ByteArrayOutputStream();
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document,  baos);
...
document.close();

...

PdfReader intermediary = new PdfReader(baos.toByteArray());
PdfStamper stamp = new PdfStamper(intermediary, output);
...
stamp.close();

更多观察结果

  • 您的类路径中似乎有多个iText版本,尤其是您同时使用了com.lowagie.text.pdfcom.itextpdf.text.pdf包中的两个类,即5.x版本和版本4.2、2.x或更低版本。

    混合使用不同的iText版本可能会产生最奇怪的效果。我建议您从类路径中删除所有较旧的版本,并且仅使用最新的5.x。当您称自己为iText中的菜鸟时,您甚至应该考虑切换到iText 7.x,除非您现有的基于iText 5的代码库太大而无法维护。

  • 您仅使用Document / Writer对来复制PdfReader reader中的页面并设置一些PDF / A标记。为此,您应该考虑使用Document / PdfCopy对,甚至使用PdfStamper。您的解决方案将丢弃所有动态PDF结构(注释,...)和所有文档级数据(元数据,...)。

    顺便说一下,PDF / A不仅仅是一些文档设置,这是源PDF必须已经满足的许多前提条件,否则您的输出将无法通过PDF / A验证。