首页 文章

iText - 将内容添加到现有PDF文件

提问于
浏览
45

我想用iText做以下事情:

(1)解析现有的PDF文件

(2)在文档的现有单页上添加一些数据(例如时间戳)

(3)写出文件

我似乎无法弄清楚如何用iText做到这一点 . 在伪代码中,我会这样做:

Document document = reader.read(input);
document.add(new Paragraph("my timestamp"));
writer.write(document, output);

但由于某些原因,iText的API非常复杂,我无法绕过它 . PdfReader实际上保存文档模型或其他东西(而不是吐出文档),你需要一个PdfWriter来读取它的页面......呃?

4 回答

  • 6

    iText有多种方法可以做到这一点 . PdfStamper 类是一个选项 . 但我发现最简单的方法是创建一个新的PDF文档,然后将现有文档中的各个页面导入到新的PDF中 .

    // Create output PDF
    Document document = new Document(PageSize.A4);
    PdfWriter writer = PdfWriter.getInstance(document, outputStream);
    document.open();
    PdfContentByte cb = writer.getDirectContent();
    
    // Load existing PDF
    PdfReader reader = new PdfReader(templateInputStream);
    PdfImportedPage page = writer.getImportedPage(reader, 1); 
    
    // Copy first page of existing PDF into output PDF
    document.newPage();
    cb.addTemplate(page, 0, 0);
    
    // Add your new data / text here
    // for example...
    document.add(new Paragraph("my timestamp")); 
    
    document.close();
    

    这将从 templateInputStream 读取PDF并将其写入 outputStream . 这些可能是文件流或内存流或任何适合您的应用程序 .

  • 3

    Gutch的代码很接近,但它只能在以下情况下正常工作:

    • 没有注释(链接,字段等),没有文档结构/标记内容,没有书签,没有文档级脚本等,等等......

    • 页面大小恰好是A.4(不错的赔率,但它碰巧碰到了't work on any ol' PDF)

    • 您不介意丢失所有原始文档元数据( 生产环境 者,创建日期,可能是作者/ Headers /关键字),也可能是文档ID . 你 can't 复制创建日期和文档ID,除非你对iText本身做了一些非常深刻的hackery) .

    批准的方法是反过来做 . 使用PdfStamper打开现有文档,并使用getOverContent()返回的PdfContentByte将文本(以及您可能需要的任何其他内容)直接写入页面 . 不需要第二份文件 .

    并且您可以使用ColumnText来处理布局等等...无需使用beginText(),setFontAndSize(),drawText(),drawText()...,endText()进行处理 .

  • 70

    这是我能想象到的最复杂的场景:我有一个用Ilustrator创建并用Acrobat修改的PDF文件,用AcroFields(AcroForm),我将用这个Java代码填充数据,这个PDF文件的结果是添加文档后,将修改字段中的数据 .

    实际上,在这种情况下,我动态生成一个添加到PDF的背景,该背景也是使用具有未知数据或页面数量的文档动态生成的 .

    我正在使用JBoss,这段代码在JSP文件中(应该可以在任何JSP Web服务器中使用) .

    注意:如果您使用的是IExplorer,则必须使用POST方法提交HTTP表单才能下载该文件 . 如果没有,您将在屏幕上看到PDF代码 . 这不会发生在Chrome或Firefox中 .

    <%@ page import="java.io.*, com.lowagie.text.*, com.lowagie.text.pdf.*" %><%
    
    response.setContentType("application/download");
    response.setHeader("Content-disposition","attachment;filename=listaPrecios.pdf" );  
    
    // -------- FIRST THE PDF WITH THE INFO ----------
    String str = "";
    // lots of words
    for(int i = 0; i < 800; i++) str += "Hello" + i + " ";
    // the document
    Document doc = new Document( PageSize.A4, 25, 25, 200, 70 );
    ByteArrayOutputStream streamDoc = new ByteArrayOutputStream();
    PdfWriter.getInstance( doc, streamDoc );
    // lets start filling with info
    doc.open();
    doc.add(new Paragraph(str));
    doc.close();
    // the beauty of this is the PDF will have all the pages it needs
    PdfReader frente = new PdfReader(streamDoc.toByteArray());
    PdfStamper stamperDoc = new PdfStamper( frente, response.getOutputStream());
    
    // -------- THE BACKGROUND PDF FILE -------
    // in JBoss the file has to be in webinf/classes to be readed this way
    PdfReader fondo = new PdfReader("listaPrecios.pdf");
    ByteArrayOutputStream streamFondo = new ByteArrayOutputStream();
    PdfStamper stamperFondo = new PdfStamper( fondo, streamFondo);
    // the acroform
    AcroFields form = stamperFondo.getAcroFields();
    // the fields 
    form.setField("nombre","Avicultura");
    form.setField("descripcion","Esto describe para que sirve la lista ");
    stamperFondo.setFormFlattening(true);
    stamperFondo.close();
    // our background is ready
    PdfReader fondoEstampado = new PdfReader( streamFondo.toByteArray() );
    
    // ---- ADDING THE BACKGROUND TO EACH DATA PAGE ---------
    PdfImportedPage pagina = stamperDoc.getImportedPage(fondoEstampado,1);
    int n = frente.getNumberOfPages();
    PdfContentByte background;
    for (int i = 1; i <= n; i++) {
        background = stamperDoc.getUnderContent(i);
        background.addTemplate(pagina, 0, 0);
    }
    // after this everithing will be written in response.getOutputStream()
    stamperDoc.close(); 
    %>
    

    还有另一种解决方案更简单,并解决了您的问题 . 这取决于您要添加的文本量 .

    // read the file
    PdfReader fondo = new PdfReader("listaPrecios.pdf");
    PdfStamper stamper = new PdfStamper( fondo, response.getOutputStream());
    PdfContentByte content = stamper.getOverContent(1);
    // add text
    ColumnText ct = new ColumnText( content );
    // this are the coordinates where you want to add text
    // if the text does not fit inside it will be cropped
    ct.setSimpleColumn(50,500,500,50);
    ct.setText(new Phrase(str, titulo1));
    ct.go();
    
  • 42
    Document document = new Document();
        PdfWriter writer = PdfWriter.getInstance(document, 
            new FileOutputStream("E:/TextFieldForm.pdf"));
        document.open();
    
        PdfPTable table = new PdfPTable(2);
        table.getDefaultCell().setPadding(5f); // Code 1
        table.setHorizontalAlignment(Element.ALIGN_LEFT);
        PdfPCell cell;      
    
        // Code 2, add name TextField       
        table.addCell("Name"); 
        TextField nameField = new TextField(writer, 
            new Rectangle(0,0,200,10), "nameField");
        nameField.setBackgroundColor(Color.WHITE);
        nameField.setBorderColor(Color.BLACK);
        nameField.setBorderWidth(1);
        nameField.setBorderStyle(PdfBorderDictionary.STYLE_SOLID);
        nameField.setText("");
        nameField.setAlignment(Element.ALIGN_LEFT);
        nameField.setOptions(TextField.REQUIRED);               
        cell = new PdfPCell();
        cell.setMinimumHeight(10);
        cell.setCellEvent(new FieldCell(nameField.getTextField(), 
            200, writer));
        table.addCell(cell);
    
        // force upper case javascript
        writer.addJavaScript(
            "var nameField = this.getField('nameField');" +
            "nameField.setAction('Keystroke'," +
            "'forceUpperCase()');" +
            "" +
            "function forceUpperCase(){" +
            "if(!event.willCommit)event.change = " +
            "event.change.toUpperCase();" +
            "}");
    
    
        // Code 3, add empty row
        table.addCell("");
        table.addCell("");
    
    
        // Code 4, add age TextField
        table.addCell("Age");
        TextField ageComb = new TextField(writer, new Rectangle(0,
             0, 30, 10), "ageField");
        ageComb.setBorderColor(Color.BLACK);
        ageComb.setBorderWidth(1);
        ageComb.setBorderStyle(PdfBorderDictionary.STYLE_SOLID);
        ageComb.setText("12");
        ageComb.setAlignment(Element.ALIGN_RIGHT);
        ageComb.setMaxCharacterLength(2);
        ageComb.setOptions(TextField.COMB | 
            TextField.DO_NOT_SCROLL);
        cell = new PdfPCell();
        cell.setMinimumHeight(10);
        cell.setCellEvent(new FieldCell(ageComb.getTextField(), 
            30, writer));
        table.addCell(cell);
    
        // validate age javascript
        writer.addJavaScript(
            "var ageField = this.getField('ageField');" +
            "ageField.setAction('Validate','checkAge()');" +
            "function checkAge(){" +
            "if(event.value < 12){" +
            "app.alert('Warning! Applicant\\'s age can not" +
            " be younger than 12.');" +
            "event.value = 12;" +
            "}}");      
    
    
    
        // add empty row
        table.addCell("");
        table.addCell("");
    
    
        // Code 5, add age TextField
        table.addCell("Comment");
        TextField comment = new TextField(writer, 
            new Rectangle(0, 0,200, 100), "commentField");
        comment.setBorderColor(Color.BLACK);
        comment.setBorderWidth(1);
        comment.setBorderStyle(PdfBorderDictionary.STYLE_SOLID);
        comment.setText("");
        comment.setOptions(TextField.MULTILINE | 
            TextField.DO_NOT_SCROLL);
        cell = new PdfPCell();
        cell.setMinimumHeight(100);
        cell.setCellEvent(new FieldCell(comment.getTextField(), 
            200, writer));
        table.addCell(cell);
    
    
        // check comment characters length javascript
        writer.addJavaScript(
            "var commentField = " +
            "this.getField('commentField');" +
            "commentField" +
            ".setAction('Keystroke','checkLength()');" +
            "function checkLength(){" +
            "if(!event.willCommit && " +
            "event.value.length > 100){" +
            "app.alert('Warning! Comment can not " +
            "be more than 100 characters.');" +
            "event.change = '';" +
            "}}");          
    
        // add empty row
        table.addCell("");
        table.addCell("");
    
    
        // Code 6, add submit button    
        PushbuttonField submitBtn = new PushbuttonField(writer,
                new Rectangle(0, 0, 35, 15),"submitPOST");
        submitBtn.setBackgroundColor(Color.GRAY);
        submitBtn.
            setBorderStyle(PdfBorderDictionary.STYLE_BEVELED);
        submitBtn.setText("POST");
        submitBtn.setOptions(PushbuttonField.
            VISIBLE_BUT_DOES_NOT_PRINT);
        PdfFormField submitField = submitBtn.getField();
        submitField.setAction(PdfAction
        .createSubmitForm("",null, PdfAction.SUBMIT_HTML_FORMAT));
    
        cell = new PdfPCell();
        cell.setMinimumHeight(15);
        cell.setCellEvent(new FieldCell(submitField, 35, writer));
        table.addCell(cell);
    
    
    
        // Code 7, add reset button
        PushbuttonField resetBtn = new PushbuttonField(writer,
                new Rectangle(0, 0, 35, 15), "reset");
        resetBtn.setBackgroundColor(Color.GRAY);
        resetBtn.setBorderStyle(
            PdfBorderDictionary.STYLE_BEVELED);
        resetBtn.setText("RESET");
        resetBtn
        .setOptions(
            PushbuttonField.VISIBLE_BUT_DOES_NOT_PRINT);
        PdfFormField resetField = resetBtn.getField();
        resetField.setAction(PdfAction.createResetForm(null, 0));
        cell = new PdfPCell();
        cell.setMinimumHeight(15);
        cell.setCellEvent(new FieldCell(resetField, 35, writer));
        table.addCell(cell);        
    
        document.add(table);
        document.close();
    }
    
    
    class FieldCell implements PdfPCellEvent{
    
        PdfFormField formField;
        PdfWriter writer;
        int width;
    
        public FieldCell(PdfFormField formField, int width, 
            PdfWriter writer){
            this.formField = formField;
            this.width = width;
            this.writer = writer;
        }
    
        public void cellLayout(PdfPCell cell, Rectangle rect, 
            PdfContentByte[] canvas){
            try{
                // delete cell border
                PdfContentByte cb = canvas[PdfPTable
                    .LINECANVAS];
                cb.reset();
    
                formField.setWidget(
                    new Rectangle(rect.left(), 
                        rect.bottom(), 
                        rect.left()+width, 
                        rect.top()), 
                        PdfAnnotation
                        .HIGHLIGHT_NONE);
    
                writer.addAnnotation(formField);
            }catch(Exception e){
                System.out.println(e);
            }
        }
    }
    

相关问题