我正在使用iText生成一份PDF文档,其中包含几个几乎相同信息的副本。
例如:发票。向客户提供一份副本,另一份提交,第三份提交给会计师进行簿记。
所有副本必须完全相同,除了一小段文字表明谁是副本(客户,会计,文件,...)。
有两种可能的情况(我不知道两种方案的解决方案是否相同):
a)每个副本都在不同的页面。
b)所有副本都在相同的页面(该文件将有切割孔以分离副本)。
将有一个包装器或帮助器类使用iText生成PDF,以便能够执行var pdf = HelperClass.CreateDocument(DocuemntInfo info);
之类的操作。多包拷贝问题将在这个包装器/帮助器中解决。
iText为实现这一目标提供了什么?我是否需要在不同的位置/页面中多次写入文档中的每个元素?或者iText是否提供了一种方法来将一个副本写入文档,然后将其复制到其他位置/页面?
注意:这是一个.Net项目,但是我用java和c#标记了这个问题,因为这个qustion是关于如何正确使用iText的,答案将有助于两个开发人员。
答案 0 :(得分:4)
如果每个副本都在不同的页面上,您可以创建一个新文档并多次在页面中复制。在Java中使用iText可以这样做:
// 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 first piece of text here
document.add(new Paragraph("Customer"));
// Copy second page of existing PDF into output PDF
document.newPage();
cb.addTemplate(page, 0, 0);
// Add your second piece of text here
document.add(new Paragraph("Accounting"));
// etc...
document.close();
如果您想将所有副本放在同一页上,代码类似,但不是在addTemplate(page, 0, 0)
中使用零,而是需要为正确的位置设置值;要使用的数字取决于发票的大小和形状。
另请参阅iText - add content to existing PDF file - 上面的代码基于我在该答案中编写的代码。
答案 1 :(得分:2)
以下是我看到这一点的工作方式。
PdfReader reader = new PdfReader( templatePDFPath );
Document doc = new Document();
PdfWriter writer = PdfWriter.createInstance( doc, new FileOutputStream("blah.pdf" ) );
PdfImportedPage inputPage = writer.getImportedPage( reader, 1 );
PdfDirectContent curPageContent = writer.getDirectContent();
String extraStuff[] = getExtraStuff();
for (String stuff : extraStuff) {
curPageContent.saveState();
curPageContent.addTemplate( inputPage /*, x, y*/ );
curPageContent.restoreState();
curPageContent.beginText();
curPageContent.setTextMatrix(x, y);
curPageContent.setFontAndSize( someFont, someSize );
// the actual work:
curPageContent.showText( stuff );
curPageContent.EndText();
// save the contents of curPageContent out to the file and reset it for the next page.
doc.newPage();
}
这是计算机上最少的工作。相当高效,它将导致更小的PDF。不是通过调整获得该页面的N个副本,而是拥有该页面的一个副本,该页面在N个页面上重复使用,并且在顶部进行了一些调整。
你可以做同样的事情,并使用addTemplate
中的“x,y”参数将它们全部绘制在同一页面上。由你决定。
PS:您需要提前确定setTextMatrix
的坐标。
答案 2 :(得分:1)
您也可以使用PDfCopy或PDfSmartCopy来执行此操作。
PdfReader reader = new PdfReader("Path\To\File");
Document doc = new Document();
PdfCopy copier = new PdfCopy(doc, ms1);
//PdfSmartCopy copier = new PdfSmartCopy(doc, ms1);
doc.Open();
copier.CloseStream = false;
PdfImportedPage inputPage = writer.GetImportedPage(reader, 1);
PdfContentByte curPageContent = writer.DirectContent;
for (int i = 0; i < count; i++)
{
copier.AddPage(inputPage);
}
doc.Close();
ms1.Flush();
ms1.Position = 0;
PdfCopy和PdfSmartCopy之间的区别在于PdfCopy复制每页的整个PDF,而PdfSmartCopy输出的PDF内部只包含一个副本,所有页面都引用它,从而导致文件更小,网络带宽更少它在服务器上占用更多内存,处理时间更长。