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

Lar*_*ard 2 c# pdf stream itextsharp c#-4.0

我正在尝试使用iTextSharp将文本添加到现有的PDF文件中.我一直在阅读很多帖子,包括这里的流行帖子.

我有一些不同之处:

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

所以我尝试修改代码,因此它接受一个字节数组并返回一个字节数组.我走到这一步:

  • 代码编译并运行
  • 我的out字节数组的长度与字节数组的长度不同

我的问题:

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

我不明白为什么.从我看到的每个StackOverflow帖子中,我都这样做.使用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;
        }
Run Code Online (Sandbox Code Playgroud)

Chr*_*aas 9

下面的代码展示了在内存中创建PDF然后在内存中执行第二次传递的完整示例.在尝试从流中获取原始字节之前,它执行@mkl所说的并关闭所有iText部分.它还GetOverContent()用于绘制上一个pdf的"顶部".有关详细信息,请参阅代码注释.

//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);
Run Code Online (Sandbox Code Playgroud)