2010-07-26 124 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); 
     } 
    } 
} 
相关问题