I have this code that will add a watermark on each page:
string watermarkLocation = AppDomain.CurrentDomain.BaseDirectory + "Watermark.png";
Document document = new Document();
PdfReader pdfReader = new PdfReader(fileLocation);
PdfStamper stamp = new PdfStamper(pdfReader, new FileStream(fileLocation.Replace(".pdf", "_marked.pdf"), FileMode.Create));
iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(watermarkLocation);
img.ScaleToFit(document.PageSize);
img.SetAbsolutePosition(0, 100);
PdfContentByte waterMark;
for (int page = 1; page <= pdfReader.NumberOfPages; page++)
{
waterMark = stamp.GetOverContent(page);
waterMark.AddImage(img);
}
stamp.FormFlattening = true;
stamp.Close();
return fileLocation.Replace(".pdf", "_marked.pdf");
But on PDFs that have textboxes, the image will go behind the textbox/form. I thought flattening the file will fix this, but it does not work.
I used a full image as a test but the watermark in the end will have transparency.
Here's the final code I'm using. As my comment mentioned, there's basically 2 readers/stamps, one to flatten the file and another to add the watermark.
Flatten file:
private byte[] FlattenPdfFormToBytes(PdfReader reader)
{
var memStream = new MemoryStream();
var stamper = new PdfStamper(reader, memStream) { FormFlattening = true };
stamper.Close();
return memStream.ToArray();
}
Add Watermark (which will call FlattenPdfFormToBytes):
public string AddWatermark(string fileLocation)
{
string watermarkLocation = AppDomain.CurrentDomain.BaseDirectory + "Watermark.png";
Document document = new Document();
PdfReader pdfReader = new PdfReader(fileLocation);
PdfReader pdfFlatten = new PdfReader(FlattenPdfFormToBytes(pdfReader)); // The secret sauce is this!!!
PdfStamper stamp = new PdfStamper(pdfFlatten, new FileStream(fileLocation.Replace(".pdf", "_marked.pdf"), FileMode.Create));
iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(watermarkLocation);
img.ScaleToFit(document.PageSize);
img.SetAbsolutePosition(0, 100);
PdfContentByte waterMark;
for (int page = 1; page <= pdfFlatten.NumberOfPages; page++)
{
waterMark = stamp.GetOverContent(page);
waterMark.AddImage(img);
}
stamp.Close();
return fileLocation.Replace(".pdf", "_marked.pdf");
}
Related
This was my code for itextsharp which worked ok. It displayed "Quote Only" in the middle of each page in a pdf file.
iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(Server.MapPath(#"~\Content\WaterMarkQuoteOnly.png"));
PdfReader readerOriginalDoc = new PdfReader(File(all, "application/pdf").FileContents);
int n = readerOriginalDoc.NumberOfPages;
img.SetAbsolutePosition(0, 300);
PdfGState _state = new PdfGState()
{
FillOpacity = 0.1F,
StrokeOpacity = 0.1F
};
using (MemoryStream ms = new MemoryStream())
{
using (PdfStamper stamper = new PdfStamper(readerOriginalDoc, ms, '\0', true))
{
for (int i = 1; i <= n; i++)
{
PdfContentByte content = stamper.GetOverContent(i);
content.SaveState();
content.SetGState(_state);
content.AddImage(img);
content.RestoreState();
}
}
//return ms.ToArray();
all = ms.GetBuffer();
}
This is my new itext 7 code, this also displays the watermark but the position is wrong. I was dismayed to see that you cant add an image to the canvas but you have to add ImageData when the position is being set on the image. The image is also way smaller and back to front.
var imagePath = Server.MapPath(#"~\Content\WaterMarkQuoteOnly.png");
var tranState = new iText.Kernel.Pdf.Extgstate.PdfExtGState();
tranState.SetFillOpacity(0.1f);
tranState.SetStrokeOpacity(0.1f);
ImageData myImageData = ImageDataFactory.Create(imagePath, false);
Image img = new Image(myImageData);
img.SetFixedPosition(0, 300);
var reader = new PdfReader(new MemoryStream(all));
var doc = new PdfDocument(reader);
int pages = doc.GetNumberOfPages();
using (var ms = new MemoryStream())
{
var writer = new PdfWriter(ms);
var newdoc = new PdfDocument(writer);
for (int i = 1; i <= pages; i++)
{
//get existing page
PdfPage page = doc.GetPage(i);
//copy page to new document
newdoc.AddPage(page.CopyTo(newdoc)); ;
//get our new page
PdfPage newpage = newdoc.GetPage(i);
Rectangle pageSize = newpage.GetPageSize();
//get canvas based on new page
var canvas = new PdfCanvas(newpage);
//write image data to new page
canvas.SaveState().SetExtGState(tranState);
canvas.AddImage(myImageData, pageSize, true);
canvas.RestoreState();
}
newdoc.Close();
all = ms.GetBuffer();
ms.Flush();
}
You are doing something strange with the PdfDocument objects, and you are also using the wrong AddImage() method.
I am not a C# developer, so I rewrote your example in Java. I took this PDF file:
And I took this image:
Then I added the image to the PDF file using transparency with the following result:
The code to do this, was really simple:
public void createPdf(String src, String dest) throws IOException {
PdfExtGState tranState = new PdfExtGState();
tranState.setFillOpacity(0.1f);
ImageData img = ImageDataFactory.create(IMG);
PdfReader reader = new PdfReader(src);
PdfWriter writer = new PdfWriter(dest);
PdfDocument pdf = new PdfDocument(reader, writer);
for (int i = 1; i <= pdf.getNumberOfPages(); i++) {
PdfPage page = pdf.getPage(i);
PdfCanvas canvas = new PdfCanvas(page);
canvas.saveState().setExtGState(tranState);
canvas.addImage(img, 36, 600, false);
canvas.restoreState();
}
pdf.close();
}
For some reason, you created two PdfDocument instances. This isn't necessary. You also used the AddImage() method passing a Rectangle which resizes the image. Also make sure that you don't add the image as an inline image, because that bloats the file size.
I don't know which programming language you are using. For instance: I am not used to variables that are created using var such as var tranState. It should be very easy for you to adapt my Java code though. It's just a matter of changing lowercases into uppercases.
I am using iTextSharp in asp.net (C#) in order to merge more than one PDf template. There is a functionality of print which prints only data of the template. While merging the templates the fields/Controls which are available in the template is renamed using RenameField Method of iTextSharp.
This implementation has broken the Print functionality. As the Print functionality has been written according to the fields.
For merging Templates, I am using a PDFCopy.
Document document = new Document();
bool flag = true;
using (FileStream fileStream = File.Create(newFile))
{
PdfSmartCopy copy = new PdfSmartCopy(document, fileStream);
PdfReader reader;
MemoryStream baos;
for (int i = 0; i < loopCount; i++)
{
reader = new PdfReader(pdfTemplate);
baos = new MemoryStream();
stamper = new PdfStamper(reader, baos);
AcroFields pdfDoc = stamper.AcroFields;
BuildData(datarow,pdfDoc, obj)
renameFields(reader);
stamper.FormFlattening = false;
stamper.Close();
reader = new PdfReader(baos.ToArray());
copy.AddPage(copy.GetImportedPage(reader, 1));
}
document.Close();
strFileName = newFile;
}
private static void renameFields(PdfReader pdfReader)
{
string prepend = String.Format("_{0}", counter++);
foreach (KeyValuePair<string, AcroFields.Item> de in pdfReader.AcroFields.Fields)
{
pdfReader.AcroFields.RenameField(de.Key.ToString(), prepend + de.Key.ToString());
}
}
Edit1: This is the solution i found in itextsharp doc,BUT it's not working
"Using PdfCopy with documents
that have named destinations is one of these exceptions. All annotations, such
as link annotations, are kept with PdfCopy, but they no longer work for links to local
named destinations. There is a workaround for this problem."
PdfReader[] readers = {
new PdfReader(LinkActions.RESULT2),
new PdfReader(LinkActions.RESULT1) };
Document document = new Document();
PdfCopy copy =
new PdfCopy(document, new FileOutputStream(RESULT1));
document.open();
int n;
for (int i = 0; i < readers.length; i++) {
readers[i].consolidateNamedDestinations();
n = readers[i].getNumberOfPages();
for (int page = 0; page < n; ) {
copy.addPage(copy.getImportedPage(readers[i], ++page));
}
}
The forms no longer work because you have forgotten to add a single line: copy.setMergeFields();
See the MergeForms2 example:
public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
Document document = new Document();
PdfCopy copy = new PdfSmartCopy(document, new FileOutputStream(dest));
copy.setMergeFields();
document.open();
List<PdfReader> readers = new ArrayList<PdfReader>();
for (int i = 0; i < 3; ) {
PdfReader reader = new PdfReader(renameFields(src, ++i));
readers.add(reader);
copy.addDocument(reader);
}
document.close();
for (PdfReader reader : readers) {
reader.close();
}
}
public byte[] renameFields(String src, int i) throws IOException, DocumentException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, baos);
AcroFields form = stamper.getAcroFields();
Set<String> keys = new HashSet<String>(form.getFields().keySet());
for (String key : keys) {
form.renameField(key, String.format("%s_%d", key, i));
}
stamper.close();
reader.close();
return baos.toByteArray();
}
It seems that you're also making the assumption that your template consists of only one page:
copy.addPage(copy.getImportedPage(reader, 1));
It is safer to add the document all at once:
copy.addDocument(reader);
Important:
My examples are written in Java. You are working with iTextSharp in C#. You will have to adapt the methods by changing the Java-specific methods into C#-specific properties or methods.
I am trying to read some pdf files page by page and add the pages to an existing pdf using itextsharp. Here is my solution:
string path2 = Server.MapPath("~/2.pdf");
PdfReader reader = null;
iTextSharp.text.Document document = null;
PdfCopy pdfCopyProvider = null;
PdfImportedPage importedPage = null;
foreach (var pdfName in pdfNames)
{
path1 = Path.Combine(Server.MapPath("~/Files/Pdf/temp/"), pdfName);
reader = new PdfReader(path1);
for (int pageIndex = 1; pageIndex <= reader.NumberOfPages; pageIndex++)
{
document = new iTextSharp.text.Document(reader.GetPageSizeWithRotation(pageIndex));
pdfCopyProvider = new PdfCopy(document, new System.IO.FileStream(path2, System.IO.FileMode.Append));
document.Open();
importedPage = pdfCopyProvider.GetImportedPage(reader, pageIndex);
iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(importedPage);
pdfCopyProvider.AddPage(importedPage);
}
reader.Close();
document.Close();
}
But the output pdf just contains the pages of last pdf in the foreach loop.
I looked into iTextSharp and SharpPDF and Report.Net as well as PDFSharp.
None of these open source projects have good documentation OR do not work with VS 2012.
Does anyone have a recommended solution or can show me the documentation?
My employer blocks many sites and although Google is not blocked, some of the results are.
I plan on using C# with WinForms and obtaining my data from an Access DB
Hey #Cocoa Dev get this a complete example with diferent functions.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using iTextSharp.text.pdf;
using System.Data;
using System.Text;
using System.util.collections;
using iTextSharp.text;
using System.Net.Mail;
public partial class PDFScenarios : System.Web.UI.Page
{
public string P_InputStream = "~/MyPDFTemplates/ex1.pdf";
public string P_InputStream2 = "~/MyPDFTemplates/ContactInfo.pdf";
public string P_InputStream3 = "~/MyPDFTemplates/MulPages.pdf";
public string P_InputStream4 = "~/MyPDFTemplates/CompanyLetterHead.pdf";
public string P_OutputStream = "~/MyPDFOutputs/ex1_1.pdf";
//Read all 'Form values/keys' from an existing multi-page PDF document
public void ReadPDFformDataPageWise()
{
PdfReader reader = new PdfReader(Server.MapPath(P_InputStream3));
AcroFields form = reader.AcroFields;
try
{
for (int page = 1; page <= reader.NumberOfPages; page++)
{
foreach (KeyValuePair<string, AcroFields.Item> kvp in form.Fields)
{
switch (form.GetFieldType(kvp.Key))
{
case AcroFields.FIELD_TYPE_CHECKBOX:
case AcroFields.FIELD_TYPE_COMBO:
case AcroFields.FIELD_TYPE_LIST:
case AcroFields.FIELD_TYPE_RADIOBUTTON:
case AcroFields.FIELD_TYPE_NONE:
case AcroFields.FIELD_TYPE_PUSHBUTTON:
case AcroFields.FIELD_TYPE_SIGNATURE:
case AcroFields.FIELD_TYPE_TEXT:
int fileType = form.GetFieldType(kvp.Key);
string fieldValue = form.GetField(kvp.Key);
string translatedFileName = form.GetTranslatedFieldName(kvp.Key);
break;
}
}
}
}
catch
{
}
finally
{
reader.Close();
}
}
//Read and alter form values for only second and
//third page of an existing multi page PDF doc.
//Save the changes in a brand new pdf file.
public void ReadAlterPDFformDataInSelectedPages()
{
PdfReader reader = new PdfReader(Server.MapPath(P_InputStream3));
reader.SelectPages("1-2"); //Work with only page# 1 & 2
using (PdfStamper stamper = new PdfStamper(reader, new FileStream(Server.MapPath(P_OutputStream), FileMode.Create)))
{
AcroFields form = stamper.AcroFields;
var fieldKeys = form.Fields.Keys;
foreach (string fieldKey in fieldKeys)
{
//Replace Address Form field with my custom data
if (fieldKey.Contains("Address"))
{
form.SetField(fieldKey, "MyCustomAddress");
}
}
//The below will make sure the fields are not editable in
//the output PDF.
stamper.FormFlattening = true;
}
}
//Extract text from an existing PDF's second page.
private string ExtractText()
{
PdfReader reader = new PdfReader(Server.MapPath(P_InputStream3));
string txt = PdfTextExtractor.GetTextFromPage(reader, 2, new LocationTextExtractionStrategy());
return txt;
}
//Create a brand new PDF from scratch and without a template
private void CreatePDFNoTemplate()
{
Document pdfDoc = new Document();
PdfWriter writer = PdfWriter.GetInstance(pdfDoc, new FileStream(Server.MapPath(P_OutputStream), FileMode.OpenOrCreate));
pdfDoc.Open();
pdfDoc.Add(new Paragraph("Some data"));
PdfContentByte cb = writer.DirectContent;
cb.MoveTo(pdfDoc.PageSize.Width / 2, pdfDoc.PageSize.Height / 2);
cb.LineTo(pdfDoc.PageSize.Width / 2, pdfDoc.PageSize.Height);
cb.Stroke();
pdfDoc.Close();
}
private void fillPDFForm()
{
string formFile = Server.MapPath(P_InputStream);
string newFile = Server.MapPath(P_OutputStream);
PdfReader reader = new PdfReader(formFile);
using (PdfStamper stamper = new PdfStamper(reader, new FileStream(newFile, FileMode.Create)))
{
AcroFields fields = stamper.AcroFields;
// set form fields
fields.SetField("name", "John Doe");
fields.SetField("address", "xxxxx, yyyy");
fields.SetField("postal_code", "12345");
fields.SetField("email", "johndoe#xxx.com");
// flatten form fields and close document
stamper.FormFlattening = true;
stamper.Close();
}
}
//Helper functions
private void SendEmail(MemoryStream ms)
{
MailAddress _From = new MailAddress("XXX#domain.com");
MailAddress _To = new MailAddress("YYY#a.com");
MailMessage email = new MailMessage(_From, _To);
Attachment attach = new Attachment(ms, new System.Net.Mime.ContentType("application/pdf"));
email.Attachments.Add(attach);
SmtpClient mailSender = new SmtpClient("Gmail-Server");
mailSender.Send(email);
}
private void DownloadAsPDF(MemoryStream ms)
{
Response.Clear();
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = "application/pdf";
Response.AppendHeader("Content-Disposition", "attachment;filename=abc.pdf");
Response.OutputStream.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
Response.OutputStream.Flush();
Response.OutputStream.Close();
Response.End();
ms.Close();
}
//Working with Memory Stream and PDF
public void CreatePDFFromMemoryStream()
{
//(1)using PDFWriter
Document doc = new Document();
MemoryStream memoryStream = new MemoryStream();
PdfWriter writer = PdfWriter.GetInstance(doc, memoryStream);
doc.Open();
doc.Add(new Paragraph("Some Text"));
writer.CloseStream = false;
doc.Close();
//Get the pointer to the beginning of the stream.
memoryStream.Position = 0;
//You may use this PDF in memorystream to send as an attachment in an email
//OR download as a PDF
SendEmail(memoryStream);
DownloadAsPDF(memoryStream);
//(2)Another way using PdfStamper
PdfReader reader = new PdfReader(Server.MapPath(P_InputStream2));
using (MemoryStream ms = new MemoryStream())
{
PdfStamper stamper = new PdfStamper(reader, ms);
AcroFields fields = stamper.AcroFields;
fields.SetField("SomeField", "MyValueFromDB");
stamper.FormFlattening = true;
stamper.Close();
SendEmail(ms);
}
}
//Burst-- Make each page of an existing multi-page PDF document
//as another brand new PDF document
private void PDFBurst()
{
string pdfTemplatePath = Server.MapPath(P_InputStream3);
PdfReader reader = new PdfReader(pdfTemplatePath);
//PdfCopy copy;
PdfSmartCopy copy;
for (int i = 1; i < reader.NumberOfPages; i++)
{
Document d1 = new Document();
copy = new PdfSmartCopy(d1, new FileStream(Server.MapPath(P_OutputStream).Replace(".pdf", i.ToString() + ".pdf"), FileMode.Create));
d1.Open();
copy.AddPage(copy.GetImportedPage(reader, i));
d1.Close();
}
}
//Copy a set of form fields from an existing PDF template/doc
//and keep appending to a brand new PDF file.
//The copied set of fields will have different values.
private void AppendSetOfFormFields()
{
PdfCopyFields _copy = new PdfCopyFields(new FileStream(Server.MapPath(P_OutputStream), FileMode.Create));
_copy.AddDocument(new PdfReader(a1("1")));
_copy.AddDocument(new PdfReader(a1("2")));
_copy.AddDocument(new PdfReader(new FileStream(Server.MapPath("~/MyPDFTemplates/Myaspx.pdf"), FileMode.Open)));
_copy.Close();
}
//ConcatenateForms
private byte[] a1(string _ToAppend)
{
using (var existingFileStream = new FileStream(Server.MapPath(P_InputStream), FileMode.Open))
using (MemoryStream stream = new MemoryStream())
{
// Open existing PDF
var pdfReader = new PdfReader(existingFileStream);
var stamper = new PdfStamper(pdfReader, stream);
var form = stamper.AcroFields;
var fieldKeys = form.Fields.Keys;
foreach (string fieldKey in fieldKeys)
{
form.RenameField(fieldKey, fieldKey + _ToAppend);
}
// "Flatten" the form so it wont be editable/usable anymore
stamper.FormFlattening = true;
stamper.Close();
pdfReader.Close();
return stream.ToArray();
}
}
//Working with Image
private void AddAnImage()
{
using (var inputPdfStream = new FileStream(#"C:\MyInput.pdf", FileMode.Open))
using (var inputImageStream = new FileStream(#"C:\img1.jpg", FileMode.Open))
using (var outputPdfStream = new FileStream(#"C:\MyOutput.pdf", FileMode.Create))
{
PdfReader reader = new PdfReader(inputPdfStream);
PdfStamper stamper = new PdfStamper(reader, outputPdfStream);
PdfContentByte pdfContentByte = stamper.GetOverContent(1);
var image = iTextSharp.text.Image.GetInstance(inputImageStream);
image.SetAbsolutePosition(1, 1);
pdfContentByte.AddImage(image);
stamper.Close();
}
}
//Add Company Letter-Head/Stationary to an existing pdf
private void AddCompanyStationary()
{
PdfReader reader = new PdfReader(Server.MapPath(P_InputStream2));
PdfReader s_reader = new PdfReader(Server.MapPath(P_InputStream4));
using (PdfStamper stamper = new PdfStamper(reader, new FileStream(Server.MapPath(P_OutputStream), FileMode.Create)))
{
PdfImportedPage page = stamper.GetImportedPage(s_reader, 1);
int n = reader.NumberOfPages;
PdfContentByte background;
for (int i = 1; i <= n; i++)
{
background = stamper.GetUnderContent(i);
background.AddTemplate(page, 0, 0);
}
stamper.Close();
}
}
Try this example:
using iTextSharp.text;
// Set up the fonts to be used on the pages
private Font _largeFont = new Font(Font.FontFamily.HELVETICA, 18, Font.BOLD, BaseColor.BLACK);
private Font _standardFont = new Font(Font.FontFamily.HELVETICA, 14, Font.NORMAL, BaseColor.BLACK);
private Font _smallFont = new Font(Font.FontFamily.HELVETICA, 10, Font.NORMAL, BaseColor.BLACK);
public void Build()
{
iTextSharp.text.Document doc = null;
try
{
// Initialize the PDF document
doc = new Document();
iTextSharp.text.pdf.PdfWriter writer = iTextSharp.text.pdf.PdfWriter.GetInstance(doc,
new System.IO.FileStream(System.IO.Directory.GetCurrentDirectory() + "\\ScienceReport.pdf",
System.IO.FileMode.Create));
// Set margins and page size for the document
doc.SetMargins(50, 50, 50, 50);
// There are a huge number of possible page sizes, including such sizes as
// EXECUTIVE, LEGAL, LETTER_LANDSCAPE, and NOTE
doc.SetPageSize(new iTextSharp.text.Rectangle(iTextSharp.text.PageSize.LETTER.Width,
iTextSharp.text.PageSize.LETTER.Height));
// Add metadata to the document. This information is visible when viewing the
// document properities within Adobe Reader.
doc.AddTitle("My Science Report");
doc.AddCreator("M. Lichtenberg");
doc.AddKeywords("paper airplanes");
// Add Xmp metadata to the document.
this.CreateXmpMetadata(writer);
// Open the document for writing content
doc.Open();
// Add pages to the document
this.AddPageWithBasicFormatting(doc);
this.AddPageWithInternalLinks(doc);
this.AddPageWithBulletList(doc);
this.AddPageWithExternalLinks(doc);
this.AddPageWithImage(doc, System.IO.Directory.GetCurrentDirectory() + "\\FinalGraph.jpg");
// Add page labels to the document
iTextSharp.text.pdf.PdfPageLabels pdfPageLabels = new iTextSharp.text.pdf.PdfPageLabels();
pdfPageLabels.AddPageLabel(1, iTextSharp.text.pdf.PdfPageLabels.EMPTY, "Basic Formatting");
pdfPageLabels.AddPageLabel(2, iTextSharp.text.pdf.PdfPageLabels.EMPTY, "Internal Links");
pdfPageLabels.AddPageLabel(3, iTextSharp.text.pdf.PdfPageLabels.EMPTY, "Bullet List");
pdfPageLabels.AddPageLabel(4, iTextSharp.text.pdf.PdfPageLabels.EMPTY, "External Links");
pdfPageLabels.AddPageLabel(5, iTextSharp.text.pdf.PdfPageLabels.EMPTY, "Image");
writer.PageLabels = pdfPageLabels;
}
catch (iTextSharp.text.DocumentException dex)
{
// Handle iTextSharp errors
}
finally
{
// Clean up
doc.Close();
doc = null;
}
}
You can always just create an html page and then convert that to pdf using wkhtmltopdf. This has the benefit of you not having to construct the pdf with a library such as iText. You just make a text file (html) and then pass it to the wkhtmltopdf executable.
See Calling wkhtmltopdf to generate PDF from HTML for more info.
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();
}
}