Adding Stamp/Watermark/Content over PDF using iTextSharp - c#

I am using following code:
PdfReader PDFReader = new PdfReader("C:\\file.pdf");
FileStream Stream = new FileStream("C:\\new.pdf", FileMode.Create, FileAccess.Write);
PdfStamper PDFStamper = new PdfStamper(PDFReader, Stream);
for (int iCount = 0; iCount < PDFStamper.Reader.NumberOfPages; iCount++)
{
PdfContentByte PDFData = PDFStamper.GetOverContent(iCount + 1);
BaseFont baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED);
PDFData.BeginText();
PDFData.SetColorFill(CMYKColor.LIGHT_GRAY);
PDFData.SetFontAndSize(baseFont, 80);
PDFData.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "SAMPLE DOCUMENT", 300, 400, 45);
PDFData.EndText();
}
Stream.Close();
PDFReader.Close();
PDFStamper.Close();
But PDFStamper.Close(); throws error. Also, I am not sure whether to call PDFReader.Close(); before or after PDFStamper.Close();
And watermark is not added in PDF file.

Your order of Close calls is all wrong:
Stream.Close();
PDFReader.Close();
PDFStamper.Close();
In particular the PDFStamper requires both the PDFReader and the Stream to still be open when it is getting closed.
Furthermore, unless an exception is thrown, the Stream automatically is closed during PDFStamper.Close().
Thus, use
PDFStamper.Close();
PDFReader.Close();
instead.
If you want to make sure that the Stream is getting closed in case of an exception, use a using statement.

Related

Duplicating PDF pages creates corrupted file

My program is suppost to take a single paged PDF document and duplicating the page while adding some content from an Excel table.
Everything works for editing the first page, but beyond that it creates a corrupt PDF file.
I used an if else statement in the foreach loop that is iteraing trough the excel table(for every row it creates a new page and adds it).
What it does is that there are two same copies of content on every page. The if else statement simply add the content once on the upper and the next on the lowe half and so on.
Here is the code:(ignore the non-english comments)
// open the reader
PdfReader reader = new PdfReader(btn_izberiPole.Content.ToString());
iTextSharp.text.Rectangle size = reader.GetPageSizeWithRotation(1);
Document document = new Document(size);
// open the writer
FileStream fs = new FileStream(btn_izberiCiljnoMapo.Content.ToString(), FileMode.Create, FileAccess.Write); //todo: preveri če je odprto
PdfWriter writer = PdfWriter.GetInstance(document, fs);
document.Open();
int count = 1;
var stamper = new PdfStamper(reader, fs);
foreach (string sifra in seznamSifer) //iterates trough every number to be added
{
if (count % 2 != 0) //za prvo polovico pol
{
// the pdf content
PdfContentByte cb = writer.DirectContent;
PdfImportedPage page = writer.GetImportedPage(reader, 1); //add old page
cb.AddTemplate(page, 0, 0);
var pdfContentByte = stamper.GetOverContent(1);
//prvi je sivi
iTextSharp.text.Image barcode = iTextSharp.text.Image.GetInstance(izdelajCrtnoKodo(System.Drawing.Color.LightGray, sifra), System.Drawing.Imaging.ImageFormat.Jpeg);
//barcode.ScaleToFit(200f, 15f); //tole za velikost zgornjih črtnih kod
barcode.SetAbsolutePosition(80, 235.9f);
barcode.ScaleAbsolute(new iTextSharp.text.Rectangle(91, 9.4f));
pdfContentByte.AddImage(barcode);
//druga crtna koda
barcode = iTextSharp.text.Image.GetInstance(izdelajCrtnoKodo(System.Drawing.Color.White, sifra), System.Drawing.Imaging.ImageFormat.Jpeg);
barcode.ScaleAbsolute(new iTextSharp.text.Rectangle(91, 9.4f));
barcode.SetAbsolutePosition(367, 217.4f);
pdfContentByte.AddImage(barcode);
//tretja crtna koda
barcode.ScaleAbsolute(new iTextSharp.text.Rectangle(79.4f, 8.5f)); //tole za velikost spodnje črtne kode //
barcode.SetAbsolutePosition(381.5f, 172.6f);
pdfContentByte.AddImage(barcode);
}
else //za drugo polovico
{
// the pdf content
PdfContentByte cb = writer.DirectContent;
PdfImportedPage page = writer.GetImportedPage(reader, 1); //add old page
cb.AddTemplate(page, 0, 0);
// var stamper = new PdfStamper(reader, fs);
var pdfContentByte = stamper.GetOverContent(1);
//prvi je sivi
iTextSharp.text.Image barcode = iTextSharp.text.Image.GetInstance(izdelajCrtnoKodo(System.Drawing.Color.LightGray, sifra), System.Drawing.Imaging.ImageFormat.Jpeg);
barcode.SetAbsolutePosition(80, 35.9f); //org 235.9f
barcode.ScaleAbsolute(new iTextSharp.text.Rectangle(91, 9.4f));
pdfContentByte.AddImage(barcode);
//druga crtna koda
barcode = iTextSharp.text.Image.GetInstance(izdelajCrtnoKodo(System.Drawing.Color.White, sifra), System.Drawing.Imaging.ImageFormat.Jpeg);
barcode.ScaleAbsolute(new iTextSharp.text.Rectangle(91, 9.4f));
barcode.SetAbsolutePosition(367, 217.4f);
pdfContentByte.AddImage(barcode);
//tretja crtna koda
barcode.ScaleAbsolute(new iTextSharp.text.Rectangle(79.4f, 8.5f)); //tole za velikost spodnje črtne kode //
barcode.SetAbsolutePosition(381.5f, 172.6f);
pdfContentByte.AddImage(barcode);
// stamper.Close(); //tale more bit namesto doc.close
document.NewPage();
}
count++;
/* if (count == 5) */break;
}
stamper.Close(); //tale more bit namesto doc.close
I tried several combinations by adding the file stream to be created in loop each time and some other methods. None worked so far. Any suggestions?
EDIT: I removed PDF stamper and used only writer for adding content.
One last problem I am encountering: document.Add(image) is adding images below the main layer. I can select those images in PDF but they are not visible. How can I solve this?
LAST EDIT: I solved this by using pdfContentByte.AddImage(barcode) instead of document.Add(barcode)
Thank you for your help guys! Next time I will for sure read the documentation first.

Font style is not preserved when converting HTML to PDF using ItextSharp

I'm trying to convert HTML to PDF, but the font style isn't being properly applied to the PDF. Below is my code (using itextsharp.dll):
Document document = new Document();
FileStream fs = new FileStream(fileName, FileMode.Create);
PdfWriter.GetInstance(document, fs);
document.Open();
HTMLWorker htmlWorker = new HTMLWorker(document);
string content = radEditorCollector.Content;
if (string.IsNullOrWhiteSpace(content))
{
content = AppConstants.LetterNotConfigured;
}
htmlWorker.Parse(new StringReader(content));
document.Close();
fs.Close();
//Create document list of each debtor
PdfReader pdfReader = new PdfReader(fileName);
readerList.Add(pdfReader);
You can edit your font with pdfStamper. Here is little idea. You can manage with what you need.
PdfReader pdfReader = new PdfReader(fileName);
PdfStamper pdfStamper = new PdfStamper(pdfReader, fs);
PdfContentByte pdfContentByte = pdfStamper.GetOverContent(1);
BaseFont baseFont = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1250, BaseFont.NOT_EMBEDDED);
pdfContentByte.SetColorFill(BaseColor.BLUE);
pdfContentByte.SetFontAndSize(baseFont, 8);
pdfContentByte.BeginText();
pdfContentByte.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "Here is your settings", 400, 600, 0);
pdfContentByte.EndText();
pdfStamper.Close();
readerList.Add(pdfReader);
Update:
Change only tag settings. Use before close.
pdfStamper.AcroFields.SetFieldProperty("YOUR_TAG", "textfont",
baseFont, null);

How to set zoom level to pdf using iTextSharp?

I need to set the zoom level 75% to pdf file using iTextSharp. I am using following code to set the zoom level.
PdfReader reader = new PdfReader("input.pdf".ToString());
iTextSharp.text.Document doc = new iTextSharp.text.Document(reader.GetPageSize(1));
doc.OpenDocument();
PdfWriter writer = PdfWriter.GetInstance(doc, new FileStream("Zoom.pdf", FileMode.Create));
PdfDestination pdfDest = new PdfDestination(PdfDestination.XYZ, 0, doc.PageSize.Height, 0.75f);
doc.Open();
PdfAction action = PdfAction.GotoLocalPage(1, pdfDest, writer);
writer.SetOpenAction(action);
doc.Close();
But I am getting the error "the page 1 was request but the document has only 0 pages" in the doc.Close();
You need to use PdfStamper (as indicated by mkl) instead of PdfWriter (as made clear by Chris Haas). Please take a look at the AddOpenAction example:
public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
PdfDestination pdfDest = new PdfDestination(PdfDestination.XYZ, 0, reader.getPageSize(1).getHeight(), 0.75f);
PdfAction action = PdfAction.gotoLocalPage(1, pdfDest, stamper.getWriter());
stamper.getWriter().setOpenAction(action);
stamper.close();
reader.close();
}
The result is a PDF that opens with a zoom factor of 75%.

Modifying a PDF using iTextSharp

I have a HttpModule that intercepts requests for PDF documents and I would like to add a date to the PDF and stream back to the client.
My code so far is
context.Response.ClearContent();
using (MemoryStream ms = new MemoryStream())
{
PdfReader reader = new PdfReader(document.Url + "&a=1");
PdfStamper stamper = new PdfStamper(reader, ms);
// *** Modify PDF here
stamper.Close();
context.Response.ContentType = "application/pdf";
context.Response.OutputStream.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
context.Response.OutputStream.Flush();
context.Response.OutputStream.Close();
context.Response.Flush();
context.Response.End();
}
HttpContext.Current.ApplicationInstance.CompleteRequest();
The code above works fine, but as soon as I try to modify the PDF I get a PDF Reader error 'The file is damaged and cannot be repaired', for example
TextField textField = new TextField(stamper.Writer, new Rectangle(0, 1000, 90, 600), name);
textField.Font = FontFactory.GetFont(FontFactory.HELVETICA, DEFAULT_FONT_SIZE, Font.NORMAL).BaseFont;
textField.FontSize = DEFAULT_FONT_SIZE;
textField.Rotation = 90;
PdfFormField field = textField.GetTextField();
stamper.AddAnnotation(field, page);
Does anyone know how I can solve this issue?
You continue sending stuff after the pdf, add
context.Response.End();
after:
context.Response.Flush();
Now you will send only the pdf, instead of the whole page. This sometimes fixes this issue.
You are also reading the buffer twice:
context.Response.OutputStream.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
try to add
byte[] bytes = ms.ToArray();
and then
context.Response.OutputStream.BinaryWrite(bytes);

ITextSharp insert text to an existing pdf

The title sums it all.
I want to add a text to an existing PDF file using iTextSharp, however i can't find how to do it anywhere in the web...
PS: I cannot use PDF forms.
I found a way to do it (dont know if it is the best but it works)
string oldFile = "oldFile.pdf";
string newFile = "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();
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();
I hope this can be usefull for someone =) (and post here any errors)
In addition to the excellent answers above, the following shows how to add text to each page of a multi-page document:
using (var reader = new PdfReader(#"C:\Input.pdf"))
{
using (var fileStream = new FileStream(#"C:\Output.pdf", FileMode.Create, FileAccess.Write))
{
var document = new Document(reader.GetPageSizeWithRotation(1));
var writer = PdfWriter.GetInstance(document, fileStream);
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, 12);
var multiLineString = "Hello,\r\nWorld!".Split('\n');
foreach (var line in multiLineString)
{
contentByte.ShowTextAligned(PdfContentByte.ALIGN_LEFT, line, 200, 200, 0);
}
contentByte.EndText();
contentByte.AddTemplate(importedPage, 0, 0);
}
document.Close();
writer.Close();
}
}
This worked for me and includes using OutputStream:
PdfReader reader = new PdfReader(new RandomAccessFileOrArray(Request.MapPath("Template.pdf")), null);
Rectangle size = reader.GetPageSizeWithRotation(1);
using (Stream outStream = Response.OutputStream)
{
Document document = new Document(size);
PdfWriter writer = PdfWriter.GetInstance(document, outStream);
document.Open();
try
{
PdfContentByte cb = writer.DirectContent;
cb.BeginText();
try
{
cb.SetFontAndSize(BaseFont.CreateFont(), 12);
cb.SetTextMatrix(110, 110);
cb.ShowText("aaa");
}
finally
{
cb.EndText();
}
PdfImportedPage page = writer.GetImportedPage(reader, 1);
cb.AddTemplate(page, 0, 0);
}
finally
{
document.Close();
writer.Close();
reader.Close();
}
}
Here is a method that uses stamper and absolute coordinates showed in the different PDF clients (Adobe, FoxIt and etc. )
public static void AddTextToPdf(string inputPdfPath, string outputPdfPath, string textToAdd, System.Drawing.Point point)
{
//variables
string pathin = inputPdfPath;
string pathout = outputPdfPath;
//create PdfReader object to read from the existing document
using (PdfReader reader = new PdfReader(pathin))
//create PdfStamper object to write to get the pages from reader
using (PdfStamper stamper = new PdfStamper(reader, new FileStream(pathout, FileMode.Create)))
{
//select two pages from the original document
reader.SelectPages("1-2");
//gettins the page size in order to substract from the iTextSharp coordinates
var pageSize = reader.GetPageSize(1);
// 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
Font font = new Font();
font.Size = 45;
//setting up the X and Y coordinates of the document
int x = point.X;
int y = point.Y;
y = (int) (pageSize.Height - y);
ColumnText.ShowTextAligned(pbover, Element.ALIGN_CENTER, new Phrase(textToAdd, font), x, y, 0);
}
}
Here is a method To print over images:
taken from here.
Use a different layer for your text you're putting over the images, and also make sure to use the GetOverContent() method.
string oldFile = "FileWithImages.pdf";
string watermarkedFile = "Layers.pdf";
// Creating watermark on a separate layer
// Creating iTextSharp.text.pdf.PdfReader object to read the Existing PDF Document
PdfReader reader1 = new PdfReader(oldFile);
using (FileStream fs = new FileStream(watermarkedFile, FileMode.Create, FileAccess.Write, FileShare.None))
// Creating iTextSharp.text.pdf.PdfStamper object to write Data from iTextSharp.text.pdf.PdfReader object to FileStream object
using (PdfStamper stamper = new PdfStamper(reader1, fs))
{
// Getting total number of pages of the Existing Document
int pageCount = reader1.NumberOfPages;
// Create New Layer for Watermark
PdfLayer layer = new PdfLayer("Layer", stamper.Writer);
// Loop through each Page
for (int i = 1; i <= pageCount; i++)
{
// Getting the Page Size
Rectangle rect = reader1.GetPageSize(i);
// Get the ContentByte object
PdfContentByte cb = stamper.GetOverContent(i);
// Tell the cb that the next commands should be "bound" to this new layer
cb.BeginLayer(layer);
BaseFont bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
cb.SetColorFill(BaseColor.RED);
cb.SetFontAndSize(bf, 100);
cb.BeginText();
cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "Some random blablablabla...", rect.Width / 2, rect.Height / 2, - 90);
cb.EndText();
// Close the layer
cb.EndLayer();
}
}

Categories

Resources