I'm building a web app for editing PDF files using iTextSharp.
When I try to write to the PDF, the text is getting printed behind an existing content, however I need to print it on top of it.
Can someone explain to me how can I set a depth property for my text?
This is my code
using (var reader = new PdfReader(oldFile))
{
using (var fileStream = new FileStream(newFile, FileMode.Create, FileAccess.Write))
{
var document = new Document(reader.GetPageSizeWithRotation(1));
var writer = PdfWriter.GetInstance(document, fileStream);
document.Open();
try
{
PdfContentByte cb = writer.DirectContent;
cb.BeginText();
try
{
cb.SetFontAndSize(BaseFont.CreateFont(), 12);
cb.SetTextMatrix(10, 100);
cb.ShowText("Customer Name");
}
finally
{
cb.EndText();
}
PdfImportedPage page = writer.GetImportedPage(reader, 1);
cb.AddTemplate(page, 0, 0);
}
finally
{
document.Close();
writer.Close();
reader.Close();
}
}
}
Can someone explain to me how can I set a depth property for my text?
Pdf does not have an explicit depth or z-axis property. What is drawn first, therefore, is covered by what is drawn later.
So if you want to have the template under your added text, you should pull the code adding the template before the code adding the text:
PdfContentByte cb = writer.DirectContent;
PdfImportedPage page = writer.GetImportedPage(reader, 1);
cb.AddTemplate(page, 0, 0);
cb.BeginText();
try
{
cb.SetFontAndSize(BaseFont.CreateFont(), 12);
cb.SetTextMatrix(10, 100);
cb.ShowText("Customer Name");
}
finally
{
cb.EndText();
}
Alternatively you can make use of am itextsharp feature: it actually created two content streams, the direct content and the under content, and puts the under content before the direct content.
Thus, if rearranging the code as above is not an option for you, you can instead add the background to the under content instead of the direct content.
Related
I'm using iTextSharp to modify a pdf file and to add specific data into it.
Here is the scenario I have, I have a DataTable that contains thousands of rows, each row represents a customer or client, and I have one pdf template.
I have to modify the pdf template for each row (client or customer) to add their id to the file in addition to other data and then it will be added to the DataTable for that client.
I'm using this code to do the needed job, but it times out when processing huge amount of rows or it takes at least 15 mins, 4k rows in my case- because this means opening the pdf file 4k times and modifying it as needed.
// file is the pdf tmeplate, id is the customer's id - represens 1 row in the DataTable, landingPage: is client's specific page should be added to the file
private static byte[] GeneratePdfFromPdfFile(byte[] file, int id, string landingPage)
{
try
{
using (var ms = new MemoryStream())
{
//Create an iTextSharp Document which is an abstraction of a PDF but **NOT** a PDF
var doc = new iTextSharp.text.Document();
//Create a writer that's bound to our PDF abstraction and our stream
var writer = PdfWriter.GetInstance(doc, ms);
//Open the document for writing
doc.Open();
PdfContentByte cb = writer.DirectContent;
////parse html code to xml
//iTextSharp.tool.xml.XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, srHtml);
PdfReader reader = new PdfReader(file);
for (int pageNumber = 1; pageNumber < reader.NumberOfPages + 1; pageNumber++)
{
doc.SetPageSize(reader.GetPageSizeWithRotation(1));
doc.NewPage();
//Insert to Destination on the first page
PdfImportedPage page = writer.GetImportedPage(reader, pageNumber);
int rotation = reader.GetPageRotation(pageNumber);
if (rotation == 90 || rotation == 270)
{
cb.AddTemplate(page, 0, -1f, 1f, 0, 0, reader.GetPageSizeWithRotation(pageNumber).Height);
}
else
{
cb.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
}
}
// Add a new page to the pdf file
doc.NewPage();
// set pdf open action to open the link embedded in the file.
string _embeddedURL = "http://" + landingPage + "/Default.aspx?code=" + id;
PdfAction act = new PdfAction(_embeddedURL);
writer.SetOpenAction(act);
doc.Close();
return ms.ToArray();
}
}
catch { return null; }
}
Note: I'm using ForEach loop to iterate through the DataTable rows
Your question (the text) doesn't correspond with your code (the C# part). You are asking one thing (add content to an existing PDF), and doing another thing (add an option action to an existing PDF), but regardless of what it is that you want to do, you shouldn't use PdfWriter to make a shallow copy of every page of an existing PDF (throwing away all interactivity).
You can significantly reduce the lines of code you wrote by using PdfStamper:
PdfReader reader = new PdfReader(file);
MemoryStream ms = new MemoryStream();
PdfStamper stamper = new PdfStamper(reader, ms);
string _embeddedURL = "http://" + landingPage + "/Default.aspx?code=" + id;
PdfAction act = new PdfAction(_embeddedURL);
stamper.Writer.SetOpenAction(act);
stamper.Close();
reader.Close();
return ms.ToArray();
Please read chapter 6 of my book to see why PdfWriter is the wrong class for you. PdfStamper is meant to manipulate an existing PDF document, keeping all its existing features intact.
Also be aware that you're using an old version of iText. The most recent version is iText 7. Please consult the Jump-Start tutorial for more info on using the latest iText version.
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.
I have the following problem when printing the pdf file after merge, the pdf documents get cut off.
Sometimes this happens because the documents aren't 8.5 x 11
they might be like 11 x 17.
Can we make it detect the page size and then use that same page size for those documents?
Or, if not, is it possible to have it fit to page?
Following is the code:
package com.sumit.program;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.itextpdf.text.Document;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;
public class MergePdf {
public static void main(String[] args) {
try {
List<InputStream> pdfs = new ArrayList<InputStream>();
pdfs.add(new FileInputStream("C:\\Documents and Settings\\Sumit\\Desktop\\NewEcnProject\\Document1.pdf"));
pdfs.add(new FileInputStream("C:\\Documents and Settings\\Sumit\\Desktop\\NewEcnProject\\Landscape.pdf"));
OutputStream output = new FileOutputStream("C:\\Documents and Settings\\Sumit\\Desktop\\NewEcnProject\\merge1.pdf");
MergePdf.concatPDFs(pdfs, output, true);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void concatPDFs(List<InputStream> streamOfPDFFiles,
OutputStream outputStream, boolean paginate) {
Document document = new Document();
try {
List<InputStream> pdfs = streamOfPDFFiles;
List<PdfReader> readers = new ArrayList<PdfReader>();
int totalPages = 0;
Iterator<InputStream> iteratorPDFs = pdfs.iterator();
// Create Readers for the pdfs.
int i=1;
while (iteratorPDFs.hasNext()) {
InputStream pdf = iteratorPDFs.next();
PdfReader pdfReader = new PdfReader(pdf);
System.out.println("Page size is "+pdfReader.getPageSize(1));
readers.add(pdfReader);
totalPages += pdfReader.getNumberOfPages();
i++;
}
// Create a writer for the outputstream
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
writer.setCompressionLevel(9);
document.open();
BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA,
BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
PdfContentByte cb = writer.getDirectContent(); // Holds the PDF data
PdfImportedPage page;
int currentPageNumber = 0;
int pageOfCurrentReaderPDF = 0;
Iterator<PdfReader> iteratorPDFReader = readers.iterator();
// Loop through the PDF files and add to the output.
while (iteratorPDFReader.hasNext()) {
PdfReader pdfReader = iteratorPDFReader.next();
// Create a new page in the target for each source page.
System.out.println("No. of pages "+pdfReader.getNumberOfPages());
i=0;
while (pageOfCurrentReaderPDF < pdfReader.getNumberOfPages()) {
Rectangle r=pdfReader.getPageSize(pdfReader.getPageN(pageOfCurrentReaderPDF+1));
if(r.getWidth()==792.0 && r.getHeight()==612.0)
document.setPageSize(PageSize.A4.rotate());
else
document.setPageSize(PageSize.A4);
document.newPage();
pageOfCurrentReaderPDF++;
currentPageNumber++;
i++;
page = writer.getImportedPage(pdfReader,
pageOfCurrentReaderPDF);
System.out.println("Width is "+page.getWidth());
System.out.println("Height is "+page.getHeight());
cb.newlineText();
cb.addTemplate(page, 0, 0);
// Code for pagination.
if (paginate) {
cb.beginText();
cb.setFontAndSize(bf, 9);
cb.showTextAligned(PdfContentByte.ALIGN_CENTER, ""
+ currentPageNumber + " of " + totalPages, 520,
5, 0);
cb.endText();
}
}
pageOfCurrentReaderPDF = 0;
}
outputStream.flush();
document.close();
outputStream.close();
System.out.println("Merging of Pdfs is done.......");
} catch (Exception e) {
e.printStackTrace();
} finally {
if (document.isOpen())
document.close();
try {
if (outputStream != null)
outputStream.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
}
Using the Document and PdfWriter class in combination with the addTemplate() method to merge documents is a bad idea. That's not what the addTemplate() method is meant for. You have explicitly or implicitly defined the page size for the Document you are working with. With the addTemplate() method, you add PdfImportedPage instances, and
when you add a new page with the same page size and rotation, you throw away all interactivity that exists in that page, but otherwise all is well,
when you add a new page with a different page size and rotation, you get the result you describe. Because of the difference in size, the imported page and the new page do not match. Parts get cut off, extra margins appear, rotations are different, etc.
This is all explained in chapter 6 of my book. You should use PdfCopy instead of PdfWriter. See for instance the FillFlattenMerge2 example:
Document document = new Document();
PdfCopy copy = new PdfSmartCopy(document, new FileOutputStream(dest));
document.open();
PdfReader reader;
String line = br.readLine();
// loop over readers
// add the PDF to PdfCopy
reader = new PdfReader(baos.toByteArray());
copy.addDocument(reader);
reader.close();
// end loop
document.close();
In your case, you also need to add page numbers, you can do this in a second go, as is done in the StampPageXofY example:
PdfReader reader = new PdfReader(src);
int n = reader.getNumberOfPages();
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
PdfContentByte pagecontent;
for (int i = 0; i < n; ) {
pagecontent = stamper.getOverContent(++i);
ColumnText.showTextAligned(pagecontent, Element.ALIGN_RIGHT,
new Phrase(String.format("page %s of %s", i, n)), 559, 806, 0);
}
stamper.close();
reader.close();
Or you can add them while merging, as is done in the MergeWithToc example.
Document document = new Document();
PdfCopy copy = new PdfCopy(document, new FileOutputStream(filename));
PageStamp stamp;
document.open();
int n;
int pageNo = 0;
PdfImportedPage page;
Chunk chunk;
for (Map.Entry<String, PdfReader> entry : filesToMerge.entrySet()) {
n = entry.getValue().getNumberOfPages();
for (int i = 0; i < n; ) {
pageNo++;
page = copy.getImportedPage(entry.getValue(), ++i);
stamp = copy.createPageStamp(page);
chunk = new Chunk(String.format("Page %d", pageNo));
if (i == 1)
chunk.setLocalDestination("p" + pageNo);
ColumnText.showTextAligned(stamp.getUnderContent(),
Element.ALIGN_RIGHT, new Phrase(chunk),
559, 810, 0);
stamp.alterContents();
copy.addPage(page);
}
}
document.close();
for (PdfReader r : filesToMerge.values()) {
r.close();
}
reader.close();
I strongly advise against using PdfWriter to merge documents! It's not impossible if you change the page size and the rotation of the page in the Document class, but you're making it harder on yourself. Moreover: using PdfWriter also throws away all interactivity (links, annotations,...) that exists in the pages you're merging. Your customer may experience that as a bug.
This seems like something that should be quick to do, but in practice there seems to be a problem. I have a bunch of PDF forms that include form fields and embedded javascript. I would like to remove the javascript code safely, but leave the PDF form fields intact.
So far I've been able to find lots of solutions, but all the solutions have either eliminated both the javascript and the form fields, or left both intact.
Here's solution A; it copies both form fields and javascript:
var pdfReader = new PdfReader(infilename);
using (MemoryStream memoryStream = new MemoryStream()) {
PdfCopyFields copy = new PdfCopyFields(memoryStream);
copy.AddDocument(pdfReader);
copy.Close();
File.WriteAllBytes(rawfilename, memoryStream.ToArray());
}
Alternately, I have solution B, that strips out both form fields and javascript:
Document document = new Document();
using (MemoryStream memoryStream = new MemoryStream()) {
PdfWriter writer = PdfWriter.GetInstance(document, memoryStream);
document.Open();
document.AddDocListener(writer);
for (int p = 1; p <= pdfReader.NumberOfPages; p++) {
document.SetPageSize(pdfReader.GetPageSize(p));
document.NewPage();
PdfContentByte cb = writer.DirectContent;
PdfImportedPage pageImport = writer.GetImportedPage(pdfReader, p);
int rot = pdfReader.GetPageRotation(p);
if (rot == 90 || rot == 270) {
cb.AddTemplate(pageImport, 0, -1.0F, 1.0F, 0, 0, pdfReader.GetPageSizeWithRotation(p).Height);
} else {
cb.AddTemplate(pageImport, 1.0F, 0, 0, 1.0F, 0, 0);
}
}
document.Close();
File.WriteAllBytes(rawfile, memoryStream.ToArray());
}
Does anyone know how to modify either solution A or B to eliminate the javascript but leave the form fields in place?
EDIT: Solution code is here!
using (MemoryStream memoryStream = new MemoryStream()) {
PdfStamper stamper = new PdfStamper(pdfReader, memoryStream);
for (int i = 0; i <= pdfReader.XrefSize; i++) {
object o = pdfReader.GetPdfObject(i);
PdfDictionary pd = o as PdfDictionary;
if (pd != null) {
pd.Remove(PdfName.AA);
pd.Remove(PdfName.JS);
pd.Remove(PdfName.JAVASCRIPT);
}
}
stamper.Close();
pdfReader.Close();
File.WriteAllBytes(rawfile, memoryStream.ToArray());
}
To manipulate a single PDF you should use the class PdfStamper and manipulate its contents, in your case iterating over the existing form fields and removing the JavaScript entries.
The iTextSharp sample AddJavaScriptToForm.cs corresponding to AddJavaScriptToForm.java from chapter 13 of iText in Action — 2nd Edition shows how JavaScript actions are added to fields, the central code being:
PdfStamper stamper = new PdfStamper(reader, ms);
AcroFields form = stamper.AcroFields;
AcroFields.Item fd = form.GetFieldItem("married");
PdfDictionary dictYes = (PdfDictionary) PdfReader.GetPdfObject(fd.GetWidgetRef(0));
PdfDictionary yesAction = ...;
dictYes.Put(PdfName.AA, yesAction);
Thus, to remove such JavaScript form field actions you have to iterate over all those PDF form fields and remove the /AA values in the associated dictionaries:
dictXXX.Remove(PdfName.AA);
EDIT: (provided by Ted Spence) Here is the final code that successfully removes javascript while leaving all form fields intact:
using (MemoryStream memoryStream = new MemoryStream())
{
PdfStamper stamper = new PdfStamper(pdfReader, memoryStream);
for (int i = 0; i <= pdfReader.XrefSize; i++)
{
PdfDictionary pd = pdfReader.GetPdfObject(i) as PdfDictionary;
if (pd != null)
{
pd.Remove(PdfName.AA); // Removes automatic execution objects
pd.Remove(PdfName.JS); // Removes javascript objects
pd.Remove(PdfName.JAVASCRIPT); // Removes other javascript objects
}
}
stamper.Close();
pdfReader.Close();
File.WriteAllBytes(rawfile, memoryStream.ToArray());
}
EDIT: (by mkl) The solution above is somewhat overachieving because it touches each and every indirect dictionary object. On the other hand it ignores inline dictionaries (I haven't checked the spec, though; maybe all /AA, /JS, and /JAVASCRIPT entries appear only in dictionaries which have to be indirect objects, or at least are de-referenced by this code).
If fulfilling this task was my job, I would try and access the objects possibly carrying JavaScript more specifically.
The advantage of this overachieving procedure might be, though, that even PDF objects are inspected which currently are not specified as carrying JavaScript but will be in later PDF versions.
Add the following lines after the for loop to keep the AcroForm:
var form = pdfReader.AcroForm;
if (form != null)
writer.CopyAcroForm(reader);
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();
}
}