使用 iTextSharp 将文本添加到内存流中的现有多页 PDF 文档

Posted

技术标签:

【中文标题】使用 iTextSharp 将文本添加到内存流中的现有多页 PDF 文档【英文标题】:Adding text to existing multipage PDF document in memorystream using iTextSharp 【发布时间】:2014-07-06 12:13:06 【问题描述】:

我正在尝试使用 iTextSharp 向现有 PDF 文件添加文本。我一直在阅读很多帖子,包括popular thread here。

我有一些不同:

我的 PDF 有 X 页 我希望将所有内容都保存在内存中,并且永远不会在我的文件系统中存储文件

所以我尝试修改代码,让它接受一个字节数组并返回一个字节数组。我已经走到这一步了:

代码编译运行 我的输出字节数组的长度不同于我的输入字节数组

我的问题:

当我稍后存储修改后的字节数组并在我的 PDF 阅读器中打开它时,我看不到我添加的文本

我不明白为什么。从我看到的每篇 *** 帖子中,我都会这样做。使用DirectContent,我使用BeginText 并写一个文本。但是,无论我如何移动位置,我都看不到它。

知道我的代码中缺少什么吗?

public static byte[] WriteIdOnPdf(byte[] inPDF, string str)
        
            byte[] finalBytes;

            // open the reader
            using (PdfReader reader = new PdfReader(inPDF))
            
                Rectangle size = reader.GetPageSizeWithRotation(1);
                using (Document document = new Document(size))
                
                    // open the writer
                    using (MemoryStream ms = new MemoryStream())
                    
                        using (PdfWriter writer = PdfWriter.GetInstance(document, ms))
                        
                            document.Open();

                            for (var i = 1; i <= reader.NumberOfPages; i++)
                            
                                document.NewPage();

                                var baseFont = BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
                                var importedPage = writer.GetImportedPage(reader, i);

                                var contentByte = writer.DirectContent;
                                contentByte.BeginText();
                                contentByte.SetFontAndSize(baseFont, 18);

                                var multiLineString = "Hello,\r\nWorld!";

                                contentByte.ShowTextAligned(PdfContentByte.ALIGN_LEFT, multiLineString,100, 200, 0);


                                contentByte.EndText();
                                contentByte.AddTemplate(importedPage, 0, 0);
                            

                            document.Close();
                            ms.Close();
                            writer.Close();
                            reader.Close();
                        

                        finalBytes = ms.ToArray();
                    

                

            

            return finalBytes;
        

【问题讨论】:

在关闭 writer 之前关闭内存流。但是关闭期间的作者试图向流中写入一些东西。您首先将添加的内容写在目标页面上,然后将原始页面放在其上方。因此,可以覆盖添加。 【参考方案1】:

下面的代码展示了一个在内存中创建 PDF 然后在内存中执行第二遍的完整示例。它执行@mkl 所说的操作并在尝试从流中获取原始字节之前关闭所有 iText 部分。它还使用GetOverContent() 在前一个 pdf 的“顶部”绘制。更多详细信息请参见代码 cmets。

//Bytes will hold our final PDFs
byte[] bytes;

//Create an in-memory PDF
using (var ms = new MemoryStream()) 
    using (var doc = new Document()) 
        using (var writer = PdfWriter.GetInstance(doc, ms)) 
            doc.Open();

            //Create a bunch of pages and add text, nothing special here
            for (var i = 1; i <= 10; i++) 
                doc.NewPage();
                doc.Add(new Paragraph(String.Format("First Pass - Page 0", i)));
            

            doc.Close();
        
    

    //Right before disposing of the MemoryStream grab all of the bytes
    bytes = ms.ToArray();


//Another in-memory PDF
using (var ms = new MemoryStream()) 
    //Bind a reader to the bytes that we created above
    using (var reader = new PdfReader(bytes)) 
        //Store our page count
        var pageCount = reader.NumberOfPages;

        //Bind a stamper to our reader
        using (var stamper = new PdfStamper(reader, ms)) 

            //Setup a font to use
            var baseFont = BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);

            //Loop through each page
            for (var i = 1; i <= pageCount; i++) 
                //Get the raw PDF stream "on top" of the existing content
                var cb = stamper.GetOverContent(i);

                //Draw some text
                cb.BeginText();
                cb.SetFontAndSize(baseFont, 18);
                cb.ShowText(String.Format("Second Pass - Page 0", i));
                cb.EndText();
            
        
    

    //Once again, grab the bytes before closing things out
    bytes = ms.ToArray();


//Just to see the final results I'm writing these bytes to disk but you could do whatever
var testFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "test.pdf");
System.IO.File.WriteAllBytes(testFile, bytes);

【讨论】:

以上是关于使用 iTextSharp 将文本添加到内存流中的现有多页 PDF 文档的主要内容,如果未能解决你的问题,请参考以下文章

使用 itextsharp 将图像 html 旁边的文本放置到 pdf

使用 iTextSharp 将多个页面添加到 pdf 表单

使用 itextsharp 在现有 pdf 中插入文本

使用 PDF itextSharp 可以在创建 pdf 文档时将图像放在文本之上

将文本添加到PDF

iTextsharp 将语言添加到 PDF 文档