web-dev-qa-db-ja.com

iText-既存のPDFファイルにコンテンツを追加

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が必要です...え?

46
Wouter Lievens

iTextにはこれを行う方法が複数あります。 PdfStamperクラスは1つのオプションです。しかし、最も簡単な方法は、新しい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に書き出します。これらはファイルストリーム、メモリストリーム、またはアプリケーションに適したものです。

70
gutch

Gutchのコードはcloseですが、次の場合にのみ正しく機能します:

  • 注釈(リンク、フィールドなど)、文書構造/マーク付きコンテンツ、ブックマーク、文書レベルのスクリプトなど、などはありません。
  • ページサイズはたまたまA.4(まともなオッズですが、どのol 'でも機能しません' PDF偶然出くわす)
  • すべての元のドキュメントメタデータ(プロデューサー、作成日、場合によっては作成者/タイトル/キーワード)およびドキュメントIDを失うことは問題ありません。 できない iText自体にかなり深いハッカーを行わない限り、作成日とドキュメントIDをコピーします)。

承認された方法は、その逆の方法です。 PdfStamperで既存のドキュメントを開き、getOverContent()から返されたPdfContentByteを使用して、テキスト(および必要なもの)をページに直接書き込みます。 2番目のドキュメントは必要ありません。

また、ColumnTextを使用してレイアウトなどを処理できます。beginText()、setFontAndSize()、drawText()、drawText()...、endText()を使用して作業を中断する必要はありません。

42
Mark Storer

これは私が想像できる最も複雑なシナリオです。Ilustratorで作成され、Acrobatで変更されたPDFファイルがあり、このJavaコードでデータを入力するAcroFields(AcroForm)があります。フィールドにデータがある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();
6
Alfred
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);
        }
    }
}
3
Ramesh. Veguru