2010-07-26 123 views
43

我想要做的iText如下:iText的 - 將內容添加到現有的PDF文件

(1)分析現有的PDF文件

(2)一些數據添加到它,現有的單頁文檔(如時間戳)

(3)寫出來的文檔

我似乎無法弄清楚如何使用iText的做到這一點的。在僞代碼中,我這樣做:

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

但由於某些原因的iText的API是如此複雜,令人生畏,我不能換我的頭周圍。 PdfReader實際上包含文檔模型或其他內容(而不是吐出文檔),並且您需要一個PdfWriter來從中讀取頁面......呃?

回答

67

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(); 

這將在一個PDF從templateInputStream讀取和寫出來給outputStream。這些可能是文件流或內存流或任何適合您的應用程序的內容。

+10

感謝。如果您不想將其限制爲A4,則可以添加document.setPageSize(reader.getPageSize(1)); – Dittimon 2012-02-23 23:38:47

+0

當我使用這種方法時,PDF出來都沒有對齊。因此,我與Mark Storer的回答一起使用了PdfStamper。 – 2017-07-10 14:20:45

+0

這是行得通的,但帶有acrofields的頁面不會在cb.addTemplate(page,0,0)中與它們一起復制。 Acofields不可用於輸出pdf – Vicky 2017-11-01 07:07:10

40

Gutch的代碼是接近,但它只會工作的權利,如果:

  • 沒有註釋(鏈接,域等),沒有文檔結構/標記的內容,沒有書籤,沒有文件水平腳本等,等等,等等...
  • 頁面大小恰好是A.4(不錯的賠率,但它不會在你遇到的任何醇'PDF上工作)
  • 你不用不介意丟失所有原始文檔元數據(生產者,創建日期,可能的作者/標題/關鍵字),也可能是文檔ID。你不能複製創建日期和文檔ID,除非你在iText本身做了一些非常深入的討論)。

批准的方法是反其道而行之。使用PdfStamper打開現有文檔,並使用getOverContent()中返回的PdfContentByte將文本(以及任何您可能需要的內容)直接寫入頁面。沒有第二個文件需要。 (),setFontAndSize(),drawText(),drawText()...,endText()方法可以使用ColumnText來處理佈局等。 。

+0

所有優點......這是確定'PdfStamper'還是'addTemplate'方法對您的方案更好的好方法。在我的例子中,'addTemplate'顯然是更好的,因爲你的觀點:我得到一個由Adobe Illustrator生成的圖形設計器的源模板,有大量的垃圾和元數據,重量爲1MB。如果我使用了'PdfStamper',則生成的文檔將爲1MB +,並且具有合同圖形設計器的名稱;通過使用'addDocument',他們的文檔是50kB,並且沒有嵌入個人信息。 – gutch 2011-03-20 00:37:29

+0

哇。這是一個巨大的尺寸變化。元數據不是那麼大......什麼佔據了剩下的空間?! – 2011-03-21 17:43:19

+0

我認爲那些大的PDF文件會選中'Preserve Illustrator編輯功能'複選框,它將文件中的所有Adobe Illustrator信息保存爲允許進一步編輯。這有點像從文檔創建PDF並將源DOC文件嵌入到文檔中。 – gutch 2011-03-23 04:24:05

5

這是我可以想象到的最複雜的場景:我有一個使用Ilustrator創建的PDF文件,並使用Acrobat進行了修改,使AcroField(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(); 
3
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); 
     } 
    } 
} 
相關問題