简体   繁体   中英

Adding text to existing multipage PDF document in memorystream using iTextSharp

I am trying to add text to an existing PDF file using iTextSharp. I have been reading many posts, including the popular thread here .

I have some differences:

  • My PDF are X pages long
  • I want to keep everything in memory, and never have a file stored on my filesystem

So I tried to modify the code, so it takes in a byte array and returns a byte array. I have come this far:

  • The code compiles and runs
  • My out byte array has a different length than my in byte array

My problem:

  • I cannot see my added text when i later store the modified byte array and open it in my PDF reader

I don't get why. From every StackOverflow post I have seen, I do the same. using the DirectContent , I use BeginText and write a text. However, i cannot see it, no matter how I move the position around.

Any idea what is missing from my code?

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;
        }

The code below shows off a full-working example of creating a PDF in memory and then performing a second pass, also in memory. It does what @mkl says and closes all iText parts before trying to grab the raw bytes from the stream. It also uses GetOverContent() to draw "on top" of the previous pdf. See the code comments for more details.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM