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

我想用iText做以下事情:

(1)parsing现有的PDF文件

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

(3)写出文件

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

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

但由于某种原因,iText的API非常复杂,我无法将其包裹起来。 PdfReader实际上包含文档模型或其他东西(而不是吐出一个文档),并且你需要一个PdfWriter来读取它的页面…呃?

iText有不止一种方法来做到这一点。 PdfStamper类是一个选项。 但是我发现最简单的方法是创build一个新的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 。 这些可能是文件stream或内存stream或任何适合您的应用程序。

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

  • 没有注释(链接,字段等),没有文档结构/标记内容,没有书签,没有文档级脚本等,等等等等。
  • 页面大小恰好是A.4(相当可观,但是对于碰巧遇到的任何其他PDF文件都不起作用)
  • 您不介意丢失所有原始文档元数据(生产者,创builddate,可能的作者/标题/关键字),也可能是文档ID。 你不能复制创builddate和文档ID,除非你在iText上做了一些非常深入的讨论)。

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

你可以使用ColumnText来处理布局,这样你就不需要用beginText(),setFontAndSize(),drawText(),drawText()…,endText()来弄脏和弄脏。

这是我能想象到的最复杂的场景:我有一个使用Ilustrator创build的PDF文件,并用Acrobat修改了AcroField(AcroForm),我将用这个Java代码填充数据,该PDF文件的结果数据在字段中被修改添加一个Document。

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

我正在使用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(); %> 

还有另一种解决scheme更简单,并解决您的问题。 这取决于你想添加的文本的数量。

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