How can I paste text onto each page of a PDF document? - c#

I'm using itextsharp to try and post text on each page of a PDF document. I've got it working so that text is pasted to the first page, but it won't work for the other pages in the document. The basic idea of what my program does is it scans in forms and saves the images to a temporary PDF doc. Each page has a special code that I want to print to the corresponding page in the new PDF doc.
Here is my code:
PdfReader reader = new PdfReader(session.getTempDir() + "temp.pdf");
PdfStamper stamper = new PdfStamper(reader, new FileStream(session.getPDFDir() + session.getFile() + ".pdf", FileMode.Append));
for(int i = 1; i <= reader.NumberOfPages; i++)
{
PdfContentByte cb = stamper.GetOverContent(i);
cb.BeginText();
string thisPagePrint = (String)printStrings[i - 1];
BaseFont bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
cb.SetFontAndSize(bf, 10);
cb.ShowTextAligned(1, thisPagePrint, 4, 440, -90);
cb.EndText();
stamper.Close();
reader.Close();
File.Delete(session.getTempDir() + "temp.pdf");
}
As I stated above, text is only pasted to the first page, but I would like for this to work for each page in the document. Thanks for any help anyone can provide.

Related

ItextSharp return a corrupted file after editing existing pdf file

I am new to itextSharp. What I am doing is just editing the old file and instead of saving the new file on the server I just want it to download at the time. but unfortunately after editing the file and being downloaded, file display a message cannot open the file. It may be corrupted.
Here is my code.
public FileStreamResult export( int ? id)
{
string pathin = Server.MapPath(Url.Content("~/PDF/input.pdf"));
PdfReader reader = new PdfReader(pathin);
iTextSharp.text.Rectangle size = reader.GetPageSizeWithRotation(1);
Document document = new Document(size);
// open the writer
//FileStream ms = new FileStream(pathout, FileMode.Create, FileAccess.Write);
var ms = new MemoryStream();
PdfWriter writer = PdfWriter.GetInstance(document, ms);
writer.CloseStream = false;
document.Open();
// the pdf content
PdfContentByte cb = writer.DirectContent;
// select the font properties
BaseFont bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
cb.SetColorFill(BaseColor.DARK_GRAY);
cb.SetFontAndSize(bf, 18f);
// write the text in the pdf content
cb.BeginText();
string text = "this is text";
// put the alignment and coordinates here
cb.ShowTextAligned(1, text, 500, 500, 0);
cb.EndText();
cb.BeginText();
text = "this is my post";
// put the alignment and coordinates here
cb.ShowTextAligned(1, text, 600, 400, 0);
cb.EndText();
// create the new page and add it to the pdf
PdfImportedPage page = writer.GetImportedPage(reader, 1);
cb.AddTemplate(page, 0, 0);
ms.Position = 0;
document.Close();
//ms.Close();
writer.Close();
reader.Close();
return File(ms, "application/pdf","test.pdf");
}
Any help will be really appreciated. :)
You change the position of the memory stream before closing the document:
ms.Position = 0;
document.Close();
As the trailer of the pdf in the result stream is written during the closing of the document, your change of stream position causes the pdf trailer to be written over the pdf header and the stream position thereafter to not be at the start.
Instead first close the document and the reader (the writer implicitly is closed by closing the document) and reset the stream position thereafter:
document.Close();
reader.Close();
ms.Position = 0;
return File(ms, "application/pdf","test.pdf");

Cannot access a closed file .net MVC?

wants to just add a text to an existing pdf using itextsharp
.and so far I have done.my code =>
public FileStreamResult DownloadCertificate(string UserId)
{
//get user info using UserId from database
//UserDetail UserDetail = db.UserDetails.Where(x => x.UserId == UserId).FirstOrDefault();
string oldFile = Server.MapPath("~/Content/img/tsms/Certificate/Certificate-of-Completion-Award-Template-Blue.pdf");
string newFile = Server.MapPath("~/Content/img/tsms/Certificate/newFile.pdf");
// open the reader
PdfReader reader = new PdfReader(oldFile);
Rectangle size = reader.GetPageSizeWithRotation(1);
Document document = new Document(size);
// open the writer
FileStream fs = new FileStream(newFile, FileMode.Create, FileAccess.Write);
PdfWriter writer = PdfWriter.GetInstance(document, fs);
document.Open();
// the pdf content
PdfContentByte cb = writer.DirectContent;
// select the font properties
BaseFont bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
cb.SetColorFill(BaseColor.DARK_GRAY);
cb.SetFontAndSize(bf, 8);
// write the text in the pdf content
cb.BeginText();
string text = "Some random blablablabla...";
// put the alignment and coordinates here
cb.ShowTextAligned(1, text, 520, 640, 0);
cb.EndText();
// write the text in the pdf content
cb.BeginText();
text = "Other random blabla...";
// put the alignment and coordinates here
cb.ShowTextAligned(2, text, 100, 200, 0);
cb.EndText();
// create the new page and add it to the pdf
PdfImportedPage page = writer.GetImportedPage(reader, 1);
cb.AddTemplate(page, 0, 0);
// close the streams and voilá the file should be changed :)
document.Close();
fs.Close();
writer.Close();
reader.Close();
return new FileStreamResult(fs, "application/pdf");
}
the problem is when I am trying to access the method browser showing me error like below=>
I don't know why it's giving me this kind of error.
I tried to find the solution. and I find....
FileStream "cannot access closed file"
but that is not enough for me.
and I also try to change some lines in my code. below =>
// close the streams and voilá the file should be changed :)
document.Close();
//fs.Close();
//writer.Close();
//reader.Close();
return new FileStreamResult(fs, "application/pdf");
but that change also doesn't help me. what I have done wrong in my code.(also how can I provide a download mode to the user.)
It looks to me like it's a problem with the FileStream. My educated guess would be the call to document.Close(); is also closing the FileStream.
You could try NOT reusing the same stream but rather opening up a new read-only one (which will also reset its position, by the way) and use that for the result.

Insert text in existing pdf with itextsharp

I can add a text to an existing pdf as it is explained in the url below.
But the texts stay below the images in the pdf when I add them. How can I fix this problem?
ITextSharp insert text to an existing pdf
Edit :
public void createFromPDF(string mapPath)
{
string oldFile = mapPath.Replace("Home", "") + "Content\\Uploads\\fiyat-listesi.pdf";// "oldFile.pdf";
string newFile = mapPath.Replace("Home", "") + "Content\\Uploads\\new.pdf";//"newFile.pdf";
// open the reader
PdfReader reader = new PdfReader(oldFile);
Rectangle size = reader.GetPageSizeWithRotation(1);
Document document = new Document(size);
// open the writer
FileStream fs = new FileStream(newFile, FileMode.Create, FileAccess.Write);
PdfWriter writer = PdfWriter.GetInstance(document, fs);
document.Open();
// the pdf content
PdfContentByte cb = writer.DirectContent;
// select the font properties
BaseFont bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
cb.SetColorFill(Color.RED);
cb.SetFontAndSize(bf, 8);
// write the text in the pdf content
cb.BeginText();
string text = "Some random blablablabla...";
// put the alignment and coordinates here
cb.ShowTextAligned(1, text, 520, 640, 0);
cb.EndText();
cb.BeginText();
text = "Other random blabla...";
// put the alignment and coordinates here
cb.ShowTextAligned(2, text, 100, 200, 0);
cb.EndText();
// create the new page and add it to the pdf
PdfImportedPage page = writer.GetImportedPage(reader, 1);
cb.AddTemplate(page, 0, 0);
document.NewPage();
Paragraph p = new Paragraph("aaaaaaaaaaaaaaaaaa", new Font(bf));
document.Add(p);
PdfImportedPage page2 = writer.GetImportedPage(reader, 2);
cb.AddTemplate(page2, 0, 0);
document.NewPage();
Paragraph pwe = new Paragraph("aaaaaaaaaaaaaaaaaa", new Font(bf));
document.Add(p);
cb.EndLayer();
PdfImportedPage page3 = writer.GetImportedPage(reader, 3);
cb.AddTemplate(page3, 0, 0);
// close the streams and voilá the file should be changed :)
document.Close();
fs.Close();
writer.Close();
reader.Close();
}
Two remarks:
You add the text first, then you add the image. Hence the image covers the text. That's elementary logic. If you switch the order and add the image first, then the text, the text will cover the image. That's pure common sense.
You manipulate an existing PDF by importing a PdfImportedPage and PdfWriter. That proves thaf you didn't read the documentation. You should use PdfStamper instead!
Your code is too complex. Switch to PdfStamper and add text using the ColumnText object. Don't use BeginText() / EndText(). Also: why are you using EndLayer()??? Do you have any idea what that method is meant for?

To write on the PDF draft form with iTextSharp

I want to fill draft form with itexsharp on PDF. But When I run code It doesn’t work. The data hides under PDF Format. You can see below the detail code. How can I fix it?
I think Squares which in the picture might be image format.
string oldFile ="~\Document\oldFile.pdf";
string newFile ="~\Document\newFile.pdf";
PdfReader reader = new PdfReader(oldFile);
Rectangle size = reader.GetPageSizeWithRotation(1);
Document document = new Document(size);
FileStream fs = new FileStream(newFile, FileMode.Create, FileAccess.Write);
PdfWriter writer = PdfWriter.GetInstance(document, fs);
document.Open();
PdfContentByte cb = writer.DirectContent;
BaseFont bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
cb.SetColorFill(BaseColor.DARK_GRAY); cb.SetFontAndSize(bf, 8);
cb.BeginText();
string text = TextBox1.Text;
cb.ShowTextAligned(1, text, 350, 710, 0); // or cb.SetTextMatrix(1, text, 350, 710, 0);
cb.EndText();
cb.BeginText();
text = TextBox1.Text;
cb.ShowTextAligned(2, text, 520, 640, 0);
cb.EndText();
cb.BeginText();
text = "Signature";
cb.ShowTextAligned(3, text, 100, 200, 0);
cb.EndText();
PdfImportedPage page = writer.GetImportedPage(reader, 1);
cb.AddTemplate(page, 0, 0);
document.Close();
fs.Close();
writer.Close();
reader.Close();
If this is editable form (the one which you can fill with Adobe Reader) then you should look at PdfStamper and AcroFields
Here is a good article about it http://www.codeproject.com/Articles/23112/Fill-in-PDF-Form-Fields-using-the-Open-Source-iTex
Try to put
PdfImportedPage page = writer.GetImportedPage(reader, 1);
cb.AddTemplate(page, 0, 0);
before adding your own text.
You write the text on the page, then you overlap your original pdf.
This article How to bring added images using iTextSharp in C# to the forefront suggests that z-order in PDF is determined by the order of objects added to the content. So import the source page first, then draw your texts, that should solve the problem.
The squares might as well be actual form fields. If that is the case, you can open the PDF with Acrobat to find out their names (or enumerate them through iTextSharp coding if you don't have Acrobat available) and use the PdfStamper class to actually "fill them in".

Adding text to each page of PDF with itext instead of just the first page

I'm trying to add text to each page of a PDF using this code which works great, but this code is only for adding text to the first page:
//variables
String pathin = #"C:\Users\root\Desktop\temp\test.pdf";
String pathout = #"C:\Users\root\Desktop\temp\test2.pdf";
//create a document object
//var doc = new Document(PageSize.A4);
//create PdfReader object to read from the existing document
PdfReader reader = new PdfReader(pathin);
//create PdfStamper object to write to get the pages from reader
PdfStamper stamper=new PdfStamper(reader, new FileStream(pathout, FileMode.Create));
// PdfContentByte from stamper to add content to the pages over the original content
PdfContentByte pbover = stamper.GetOverContent(1);
//add content to the page using ColumnText
ColumnText.ShowTextAligned(pbover, Element.ALIGN_LEFT, new Phrase("Hello World"), 10, 10, 0);
// PdfContentByte from stamper to add content to the pages under the original content
//PdfContentByte pbunder = stamper.GetUnderContent(1);
//close the stamper
stamper.Close();
I've seen examples using:
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);
To iterate through each page, but I'm having trouble tying that into my code above. Any helps would be much appreciated, thanks.
in your first snippet, you hardcode the page number:
stamper.GetUnderContent(1);
In your second snippet, you loop over the pages:
for (var i = 1; i <= reader.NumberOfPages; i++) {
}
Now combine these two snippets:
for (var i = 1; i <= reader.NumberOfPages; i++) {
PdfContentByte pbunder = stamper.GetUnderContent(i);
// do stuff with bunder
}

Categories