iText - add content to existing PDF file

前端 未结 4 845
温柔的废话
温柔的废话 2020-11-27 13:09

I want to do the following with iText:

(1) parse an existing PDF file

(2) add some data to it, on the existing single page of the document (such as a timesta

相关标签:
4条回答
  • 2020-11-27 13:28

    This is the most complicated scenario I can imagine: I have a PDF file created with Ilustrator and modified with Acrobat to have AcroFields (AcroForm) that I'm going to fill with data with this Java code, the result of that PDF file with the data in the fields is modified adding a Document.

    Actually in this case I'm dynamically generating a background that is added to a PDF that is also dynamically generated with a Document with an unknown amount of data or pages.

    I'm using JBoss and this code is inside a JSP file (should work in any JSP webserver).

    Note: if you are using IExplorer you must submit a HTTP form with POST method to be able to download the file. If not you are going to see the PDF code in the screen. This does not happen in Chrome or 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(); 
    %>
    

    There is another solution much simpler, and solves your problem. It depends the amount of text you want to add.

    // 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();
    
    0 讨论(0)
  • 2020-11-27 13:31
    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);
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-27 13:34

    iText has more than one way of doing this. The PdfStamper class is one option. But I find the easiest method is to create a new PDF document then import individual pages from the existing document into the new 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();
    

    This will read in a PDF from templateInputStream and write it out to outputStream. These might be file streams or memory streams or whatever suits your application.

    0 讨论(0)
  • 2020-11-27 13:42

    Gutch's code is close, but it'll only work right if:

    • There are no annotations (links, fields, etc), no Document Structure/Marked Content, no bookmarks, no document-level script, etc, etc, etc...
    • The page size happens to be A.4 (decent odds, but it won't work on any ol' PDF you happen to come across)
    • You don't mind losing all the original document metadata (producer, creation date, possibly author/title/keywords), and maybe the document ID. You can't copy the creation date and doc ID unless you do some pretty deep hackery on iText itself).

    The Approved Method is to do it the other way around. Open the existing document with a PdfStamper, and use the returned PdfContentByte from getOverContent() to write text (and whatever else you might need) directly to the page. No second document needed.

    And you can use a ColumnText to handle layout and such for you... no need to get down and dirty with beginText(),setFontAndSize(),drawText(),drawText()...,endText().

    0 讨论(0)
提交回复
热议问题