-1

I am trying to add new text to an existing PDF file but it is not adding. From the code below it doesn't show any error but the text is not added.

I have also looked at some examples below Example1 Example2

Can you please guide me if there's something I am not doing it right?

This is the code am using to write text to the pdf.

      else
        {
            if (document.State != DocumentState.Signed)
                document.State = DocumentState.Signed;

            document.ActionedUser = user;
            document.ActionDate = DateTime.Now;

      //this return bytes and it changes to document.SignedFileData = memoryStream.ToArray() and that makes it to loose original data
            document.SignedFileData = response.Document.SignedFileBytes;
            #region

            int numberOfPages;

            // create a MemoryStream to write the stamping result to
            using (MemoryStream memoryStream = new MemoryStream())
            {
                //create PdfReader object to read from the existing document
                using (PdfReader reader = new PdfReader(document.EditedFileData))
                // create a PdfStamper object to manipulate the PDF in the reader and write to the MemoryStream 
                using (PdfStamper stamper = new PdfStamper(reader, memoryStream))
                {
                    numberOfPages = reader.NumberOfPages;
                    reader.SelectPages("1-100");

                    // PdfContentByte from stamper to add content to the pages over the original content
                    PdfContentByte pbover = stamper.GetOverContent(numberOfPages);
                    iTextSharp.text.Font font = new iTextSharp.text.Font(null, 10, iTextSharp.text.Font.NORMAL, BaseColor.RED);

                    string FisrtName = "Testing";
                    string Position = "Testing";
                    string Signature = "Testing"; ;
                    string SignatureDate = DateTime.Now.ToString();

                    ColumnText.ShowTextAligned(pbover, Element.ALIGN_LEFT, new Phrase(FisrtName, font), 240, 715, 0);
                    ColumnText.ShowTextAligned(pbover, Element.ALIGN_LEFT, new Phrase(Position, font), 230, 628, 0);
                    ColumnText.ShowTextAligned(pbover, PdfContentByte.ALIGN_LEFT, new Phrase(Signature, font), 230, 600, 0);
                    ColumnText.ShowTextAligned(pbover, PdfContentByte.ALIGN_LEFT, new Phrase(SignatureDate, font), 230, 574, 0);
                }
            }

            #endregion
            // Store the manipulated PDF in the EditedFileData property
            document.SignedFileData = memoryStream.ToArray();


            Context.SaveChanges();
            return new SignatureSoapResponse() { Success = true, Message = document.Id.ToString() };
        }

PDF Table enter image description here

IT Forward
  • 367
  • 2
  • 7
  • 28
  • You are aware that you are storing the result in a file with a weird filename!? Furthermore, `System.Drawing.Point` does not appear to have a zero parameter constructor, so which `Point` class do you instantiate in `System.Drawing.Point point = new Point();`? – mkl May 19 '20 at 14:31
  • @mkl I am not aware, can you please drive me to the right direction? I am using System.Drawing.Point with the page size. I am not sure if this is wrong or if there's a better way. – IT Forward May 19 '20 at 14:38
  • The problem with the `Point` class is a mere aside as you effectively ignore `point`, `x`, and `y`, your `ColumnText.ShowTextAligned` calls have hard-coded coordinates. More important is the other observation, your code does not store the result in your `PDFFile document` object but in a file in the current folder with a weird, probably much too long name. – mkl May 19 '20 at 14:45
  • lets start with the Point , you mean i should change and make it like this ColumnText.ShowTextAligned(pbover, Element.ALIGN_LEFT, new Phrase(FisrtName, font), point.X, point.Y, 0); – IT Forward May 19 '20 at 14:50
  • *"lets start with the Point , you mean i should change ..."* - no, I mean you should explain which `Point` class you instantiate in `System.Drawing.Point point = new Point();` because as far as I can see `System.Drawing.Point` does not have a zero argument constructor. Your code should not be compilable unless `new Point()` refers to a different class. – mkl May 19 '20 at 15:07
  • The reason for me to hardcode those coordinates is because I want to place a text in a specific area in a document. I don't think there's a problem with coordinates. I am suspecting document.EditedFileData as it is in a byte array and I tried to Convert.ToBase64String with no luck as it cannot be converted to a string. This how the edited document looks like on the DB when saved. refers to the image added – IT Forward May 19 '20 at 15:08
  • So, you have a good reason for hard coded coordinates. Then why do you have that `point`, 'x', and 'y' in your code at all? If you don't use it, remove it. That being said I still wonder why you write the result into a weirdly named file in the file system instead of into a `MemoryStream` and putting its contents eventually into your `PDFFile` object. – mkl May 19 '20 at 15:14
  • I have since then remove it. Honestly, I thought FileStream is the best way to go with the hope of getting the result. Can you please tell me how I can use MemoryStream in this case? I have updated the DB image not sure if you have seen it. NB: I am new to the project and i am mainly working on maintenance. – IT Forward May 19 '20 at 15:20
  • Ok, just to be sure, you want to have the manipulated PDF to go into `document.EditedFileData`? – mkl May 19 '20 at 15:23
  • Yes, that's correct because that's the edited file. If you can check from the DB image, it illustrates the original and edited file which is the one I want to edit or editing – IT Forward May 19 '20 at 15:28
  • Ok. (I just wondered because in your DB screen shot you highlight the `NULL` entry in the `SignedFileData` column, not the `EditedFileData` entry.) – mkl May 19 '20 at 15:32
  • It is on my local DB because I didn't digitally sign the document. Probably I have cancelled before signing or while on progress. – IT Forward May 19 '20 at 15:36

1 Answers1

0

In the course of the comments it turned out that the manipulated PDF is to be stored in the EditedFileData property of the PDFFile document.

The OP's code instead stored the result PDF somewhere in the file system using weird names:

new FileStream(Convert.ToBase64String(document.EditedFileData), FileMode.Create))

This target stream of the PdfStamper takes the current content of the document.EditedFileData property, base64 encodes it, and uses it as name of a file in the file system to which the PDF is written.

To store the manipulated PDF in the document.EditedFileData property, one should instead use a MemoryStream as target stream of the PdfStamper and eventually put the memory stream contents into the property in question, i.e.:

// create a MemoryStream to write the stamping result to
using (MemoryStream memoryStream = new MemoryStream())
{
    //create PdfReader object to read from the existing document
    using (PdfReader reader = new PdfReader(document.OriginalFileData))
    // create a PdfStamper object to manipulate the PDF in the reader and write to the MemoryStream 
    using (PdfStamper stamper = new PdfStamper(reader, memoryStream))
    {
        numberOfPages = reader.NumberOfPages;
        reader.SelectPages("1-100");

        // PdfContentByte from stamper to add content to the pages over the original content
        PdfContentByte pbover = stamper.GetOverContent(numberOfPages);
        iTextSharp.text.Font font = new iTextSharp.text.Font(null, 16, iTextSharp.text.Font.BOLD, BaseColor.RED);

        string FisrtName = "Director1";
        string Position = "Director1";
        string Signature = "Director1";
        string SignatureDate = DateTime.Now.ToString();

        ColumnText.ShowTextAligned(pbover, Element.ALIGN_LEFT, new Phrase(FisrtName, font), 230, 650, 0);
        ColumnText.ShowTextAligned(pbover, Element.ALIGN_LEFT, new Phrase(Position, font), 230, 628, 0);
        ColumnText.ShowTextAligned(pbover, PdfContentByte.ALIGN_LEFT, new Phrase(Signature, font), 230, 600, 0);
        ColumnText.ShowTextAligned(pbover, PdfContentByte.ALIGN_LEFT, new Phrase(SignatureDate, font), 230, 574, 0);
    }

    // Store the manipulated PDF in the EditedFileData property
    document.EditedFileData = memoryStream.ToArray();
}
mkl
  • 90,588
  • 15
  • 125
  • 265
  • I have added this code and it seems not to be writing on the document. I tried to debug to check if some null value are being passed. I tried to add this code after reading one example but it didn't work stamper.Writer.CloseStream = true; document.EditedFileData = memoryStream.ToArray(); stamper.Close(); – IT Forward May 19 '20 at 16:49
  • Calling `ToArray` before the stamper is closed makes no sense, you'll get an incomplete pdf. I tested the code as it is in the answer and it updated the `document.EditedFileData` with a pdf with three copies of *Director1* on it. If it doesn't in your case, there is something else going wrong. – mkl May 19 '20 at 19:29
  • Do you get a pdf in `document.EditedFileData`? Does it differ from the one in `document.OriginalFileData`? (Check file sizes and contents.) – mkl May 19 '20 at 19:32
  • I do get the document that differs from original document but without newly added text. I can view the signed document but without the test, I have added, surely there's something going on which I can't figure it out..please drop your Skype handle so that we can contiue to chat if that's ok with you. – IT Forward May 20 '20 at 15:06
  • Please share an example input and output document illustrating the issue for analysis. Sorry, no free private consulting. – mkl May 20 '20 at 15:22
  • I have grabbed the table which i am supposed to add newly added text on it. This pdf comes via another system and i only have to add text after signature. – IT Forward May 20 '20 at 15:43
  • By *"example input and output document"* I meant actual pdfs, not screenshots thereof. There are a number of possible causes preventing the added text from appearing in a viewer, and I offered to check which one it may be. – mkl May 20 '20 at 15:57
  • I have cut it because it contains companies information and other data, like client's information and others – IT Forward May 20 '20 at 15:58
  • Have you tried using different, non-critical PDFs? If the same problem occurs for them, you can share them without any problem. And if the problem does not occur, then you know that there is something special about your PDFs and you have to have them analyzed by an expert. – mkl May 20 '20 at 17:11
  • I have just created a new pdf file with the table with the same fields as original document. I also created a test app for it. Now it still not writing to the new file thou am not using byte. string newContract = @"C:\Desktop\Agreement_new.pdf"; string oldContract = @"C:\Desktop\Agreement_old.pdf"; Then at the end: Don't know how to convert it(newContract =memoryStream.ToArray();) then i used the code below byte[] buffer = System.Text.Encoding.UTF8.GetBytes(newContract); string s = System.Text.Encoding.UTF8.GetString(buffer, 0, buffer.Length); – IT Forward May 20 '20 at 17:31
  • Please share the files. And concerning *"Don't know how to convert it"* - what do you want to convert it for? That encoding stuff will only damage the file... – mkl May 20 '20 at 20:24
  • After some debugging and inspecting each object and change the place where I was writing the file, it finally wrote a new text to the PDF. Please refers to the updated picture. However, every time new text added it removes the signature data of the SignedFileData – IT Forward May 20 '20 at 20:40
  • { if (document.State != DocumentState.Signed) document.State = DocumentState.Signed; document.ActionedUser = user; document.ActionDate = DateTime.Now; document.SignedFileData = response.Document.SignedFileBytes; //code to write text document.SignedFileData = memoryStream.ToArray(); Context.SaveChanges(); return new SignatureSoapResponse() { Success = true, Message = document.Id.ToString() }; } – IT Forward May 20 '20 at 20:50
  • Now the problem is that response.Document.SignedFileBytes takes bytes of memoryStream.ToArray(); and it makes it lose the data – IT Forward May 20 '20 at 20:50
  • As you should see yourself, more than one line of code here in comments is unreadable. You may want to edit your question text and add code changes, observations, and example files there. – mkl May 20 '20 at 21:00
  • the method is too big and some of the things are unnecessary to share as doesn't relate to what is giving me the problem. document.SignedFileData = response.Document.SignedFileBytes; returns signed bytes but after adding the text it changes the bytes and takes the one from the document.EditedFileData = memoryStream.ToArray(); and this makes it loose some signed data. – IT Forward May 21 '20 at 08:48
  • Probably. But the code you post is all one can go by as you don't even share example input and output pdf files to demonstrate what goes missing. – mkl May 21 '20 at 09:27
  • Each page got initials image which are byte and the moment I write the text it goes missing for each page. Hence am saying am suspecting that it is loosing response.Document.SignedFileBytes since we are assigning document.EditedFileData = memoryStream.ToArray(); and it looses data – IT Forward May 21 '20 at 09:32