I want to add page numbers to the footer of the itextsharp pdf file.Im generating pdf from html (asp.net repeater).And Im using XMLWorkerHelper to parse the html content.I searched a lot but cant find anything useful to achive this.
You'll have to open the PDF with iTextSharp and add the page numbers yourself. I did something like this a while back, here's my function that might give you a start.
The function adds the current page to the lower left, so you might have to place it somewhere else that fits your needs.
public static byte[] AddPageNumbers(byte[] pdf)
{
MemoryStream ms = new MemoryStream();
// we create a reader for a certain document
PdfReader reader = new PdfReader(pdf);
// we retrieve the total number of pages
int n = reader.NumberOfPages;
// we retrieve the size of the first page
Rectangle psize = reader.GetPageSize(1);
// step 1: creation of a document-object
Document document = new Document(psize, 50, 50, 50, 50);
// step 2: we create a writer that listens to the document
PdfWriter writer = PdfWriter.GetInstance(document, ms);
// step 3: we open the document
document.Open();
// step 4: we add content
PdfContentByte cb = writer.DirectContent;
int p = 0;
Console.WriteLine("There are " + n + " pages in the document.");
for (int page = 1; page <= reader.NumberOfPages; page++)
{
document.NewPage();
p++;
PdfImportedPage importedPage = writer.GetImportedPage(reader, page);
cb.AddTemplate(importedPage, 0, 0);
BaseFont bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
cb.BeginText();
cb.SetFontAndSize(bf, 10);
cb.ShowTextAligned(PdfContentByte.ALIGN_LEFT, +p + "/" + n, 7, 44, 0);
cb.EndText();
}
// step 5: we close the document
document.Close();
return ms.ToArray();
}
Something like this should work:
var sourceFileList = new List<string>();
//add files to merge
int sourceIndex = 0;
PdfReader reader = new PdfReader(sourceFileList[sourceIndex]);
int sourceFilePageCount = reader.NumberOfPages;
Document doc = new Document(reader.GetPageSizeWithRotation(1));
PdfWriter writer = PdfWriter.GetInstance(doc, new FileStream(destinationFileName, FileMode.Create));
doc.Open();
PdfImportedPage page;
PdfContentByte contentByte = writer.DirectContent;
int rotation;
while (sourceIndex < sourceFileList.Count)
{
int pageIndex = 0;
while (pageIndex < sourceFilePageCount)
{
pageIndex++;
doc.SetPageSize(reader.GetPageSizeWithRotation(pageIndex));
doc.NewPage();
page = writer.GetImportedPage(reader, pageIndex);
rotation = reader.GetPageRotation(pageIndex);
if (rotation.Equals(90 | 270))
contentByte.AddTemplate(page, 0, -1f, 1f, 0, 0, reader.GetPageSizeWithRotation(pageIndex).Height);
else
contentByte.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
}
sourceIndex++;
if (sourceIndex < sourceFileList.Count)
{
reader = new PdfReader(sourceFileList[sourceIndex]);
sourceFilePageCount = reader.NumberOfPages;
}
}
doc.Close();
Related
I have an existing PDF file, I want to insert a text at the bottom of PDF file in Red color, but the existing pdf file color must remain the same.
Thank You #mkl below code, I used which is specific for Stamp.
public static void ManipulatePdf(string src, string dest)
{
src = #"C:\CCPR Temp\TempFiles\PayStub_000106488_12282019_20200117112403.pdf";
dest = #"C:\CCPR Temp\TempFiles\PayStub_WithStamper.pdf";
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileStream(dest, FileMode.Create)); // create?
int numberOfPages = reader.NumberOfPages;
Rectangle pagesize;
for (int i = 1; i <= numberOfPages; i++)
{
PdfContentByte under = stamper.GetUnderContent(i);
pagesize = reader.GetPageSize(i);
float x =40;// (pagesize.Left + pagesize.Right) / 2;
float y = pagesize.Top/4;// (pagesize.Bottom + pagesize.Top) / 2;
PdfGState gs = new PdfGState();
gs.FillOpacity = 1.0f;
under.SaveState();
under.SetGState(gs);
under.SetRGBColorFill(255,0,0);
ColumnText.ShowTextAligned(under, Element.ALIGN_BOTTOM,
new Phrase("Watermark", new Font(Font.FontFamily.HELVETICA, 20)),
x, y, 1);
under.RestoreState();
}
stamper.Close();
reader.Close();
}
Adding content to an existing PDF document without changing the existing content, is sometimes referred to as stamping. Examples are adding page numbers, adding a watermark, and adding a running head.
For your specific case:
Create a PdfDocument instance from a PdfReader (to read the input PDF) and a PdfWriter (to write the output PDF). The PdfDocument instance will be in stamping mode.
Set the red text color on a Paragraph with the footer text.
Position the text with the ShowTextAligned convenience method, based on the page size.
You may also want to take into account page rotation.
PdfDocument pdfDoc = new PdfDocument(new PdfReader("input.pdf"), new PdfWriter("output.pdf"));
Document doc = new Document(pdfDoc);
Paragraph footer = new Paragraph("This is a footer").SetFontColor(ColorConstants.RED);
for (int i = 1; i <= pdfDoc.GetNumberOfPages(); i++)
{
Rectangle pageSize = pdfDoc.GetPage(i).GetPageSize();
float x = pageSize.GetLeft() + pageSize.GetWidth() / 2;
float y = pageSize.GetBottom() + 20;
doc.ShowTextAligned(footer, x, y, i, TextAlignment.CENTER, VerticalAlignment.BOTTOM, 0);
}
doc.Close();
This will set the Font of your Paragraph. I am not sure about the Position.
BaseFont btnRedFooter = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
iTextSharp.text.Font fntRedFooter = FontFactory.GetFont(iTextSharp.text.Font.FontFamily.TIMES_ROMAN.ToString(), 16,
iTextSharp.text.Font.BOLD, iTextSharp.text.BaseColor.RED);
pProtocoll.Add(new Paragraph("Text in Footer", fntRedFooter));
I used the below steps and finally, got the required output. I was struggling for the font color, to apply to the newly added text.
public static void StampPdfFile(string oldFile, string newFile)
{
// 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.SetFontAndSize(bf, 8);
// write the text in the pdf content
cb.BeginText();
string text = $"Voided On - {DateTime.Now.Date.ToString("MM/dd/yyyy")}";
// put the alignment and coordinates here
cb.SetColorFill(BaseColor.RED); //Give Red color to the newly added Text only
cb.ShowTextAligned(2, text, 120, 250, 0);
cb.SetColorFill(BaseColor.BLACK); //Give Red color to the exisitng file content only
cb.EndText();
// create the new page and add it to the pdf
PdfImportedPage page = writer.GetImportedPage(reader, 1);
cb.AddTemplate(page, 0, 0);
document.Close();
fs.Close();
writer.Close();
reader.Close();
}
I am trying to merge two PDF in this method but after successfully adding, I am unable to convert iTextSharp.text.Document into byte array . Please help me.
protected byte[] MergePDFs(byte[] First, byte[] Second, string RptTitle)
{
iTextSharp.text.Document doc = new iTextSharp.text.Document();
iTextSharp.text.pdf.PdfReader reader = null;
int numberOfPages = 0;
int currentPageNumber = 0;
iTextSharp.text.pdf.PdfWriter writer = iTextSharp.text.pdf.PdfWriter.GetInstance(doc, MemStream);
doc.Open();
iTextSharp.text.pdf.PdfContentByte cb = writer.DirectContent;
iTextSharp.text.pdf.PdfImportedPage page = null;
//Third, append all the PDFs--THIS IS THE MAGIC PART
if (First != null)
{
reader = new iTextSharp.text.pdf.PdfReader(First);
numberOfPages = reader.NumberOfPages;
currentPageNumber = 0;
while ((currentPageNumber < numberOfPages))
{
currentPageNumber += 1;
doc.SetPageSize(iTextSharp.text.PageSize.A4);
doc.NewPage();
page = writer.GetImportedPage(reader, currentPageNumber);
//we know that the page would always be in Potrait Format
cb.AddTemplate(page, 1f, 0, 0, 1f, 0, 1);
}
}
if (Second != null)
{
reader = new iTextSharp.text.pdf.PdfReader(Second);
numberOfPages = reader.NumberOfPages;
currentPageNumber = 0;
while ((currentPageNumber < numberOfPages))
{
currentPageNumber += 1;
doc.SetPageSize(iTextSharp.text.PageSize.A4.Rotate());
//.Rotate());
doc.NewPage();
page = writer.GetImportedPage(reader, currentPageNumber);
//we know that the page would always be in LandScape Format
// cb.AddTemplate(page,0, -1f, 1f, 0,0, reader.GetPageSizeWithRotation(currentPageNumber).Height+300);
cb.AddTemplate(page, 1, 0, 0, 1, 0, 0);
}
}
doc.Close();
byte[] cc = StringToByteArray(doc.ToString());
return cc;
I don't know where you people get this examples, they are completely wrong.
First, use PdfCopy, not PdfWriter. That way the correct page size and orientation will be correctly imported.
Second, if your MemStream is a MemoryStream you would use MemStream.ToArray() to get the PDF bytes.
PS: Where did that invention of doc.ToString() come from? It's completely rubbish.
I have one PDF form which is filled by supervisor(or a user).
I want to merge generated PDFs.
I have done simple merging but in it i have to first generate multiple files and then merge them.
Is there any way that when user fills multiple forms and then at the time of final submission or printing i get only a single merged of all filled PDFs.
Try out this Merge function to merge PDF files:
public static void Merge(string[] sourceFiles, string destinationFile)
{
try
{
int f = 0;
// we create a reader for a certain document
PdfReader reader = new PdfReader(sourceFiles[f]);
// we retrieve the total number of pages
int n = reader.NumberOfPages;
//Debug.WriteLine("There are " + n + " pages in the original file.");
// step 1: creation of a document-object
Document document = new Document(reader.GetPageSizeWithRotation(1));
// step 2: we create a writer that listens to the document
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(destinationFile, FileMode.Create));
// step 3: we open the document
document.Open();
PdfContentByte cb = writer.DirectContent;
PdfImportedPage page;
int rotation;
// step 4: we add content
while (f < sourceFiles.Length)
{
int i = 0;
while (i < n)
{
i++;
document.SetPageSize(reader.GetPageSizeWithRotation(i));
document.NewPage();
page = writer.GetImportedPage(reader, i);
rotation = reader.GetPageRotation(i);
if (rotation == 90 || rotation == 270)
{
cb.AddTemplate(page, 0, -1f, 1f, 0, 0, reader.GetPageSizeWithRotation(i).Height);
}
else
{
cb.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
}
//Debug.WriteLine("Processed page " + i);
}
f++;
if (f < sourceFiles.Length)
{
reader = new PdfReader(sourceFiles[f]);
// we retrieve the total number of pages
n = reader.NumberOfPages;
//Debug.WriteLine("There are " + n + " pages in the original file.");
}
}
// step 5: we close the document
document.Close();
}
catch (Exception ex)
{
throw ex;
}
}
Reference: Merge PDF Files using iTextSharp
based off the merge code I sourced in my comments above..
I use this to write to the output stream of an http response. It returns a byte[], but you can use the original code and this to get the job done.
public static byte[] MergeFiles(List<byte[]> sourceFiles)
{
Document document = new Document();
MemoryStream output = new MemoryStream();
try
{
// Initialize pdf writer
PdfWriter writer = PdfWriter.GetInstance(document, output);
// Open document to write
document.Open();
PdfContentByte content = writer.DirectContent;
// Iterate through all pdf documents
for (int fileCounter = 0; fileCounter < sourceFiles.Count; fileCounter++)
{
// Create pdf reader
PdfReader reader = new PdfReader(sourceFiles[fileCounter]);
int numberOfPages = reader.NumberOfPages;
// Iterate through all pages
for (int currentPageIndex = 1; currentPageIndex <=
numberOfPages; currentPageIndex++)
{
// Determine page size for the current page
document.SetPageSize(
reader.GetPageSizeWithRotation(currentPageIndex));
// Create page
document.NewPage();
PdfImportedPage importedPage =
writer.GetImportedPage(reader, currentPageIndex);
// Determine page orientation
int pageOrientation = reader.GetPageRotation(currentPageIndex);
if ((pageOrientation == 90) || (pageOrientation == 270))
{
content.AddTemplate(importedPage, 0, -1f, 1f, 0, 0,
reader.GetPageSizeWithRotation(currentPageIndex).Height);
}
else
{
content.AddTemplate(importedPage, 1f, 0, 0, 1f, 0, 0);
}
}
}
}
catch (Exception exception)
{
throw new Exception("There has an unexpected exception" +
" occured during the pdf merging process.", exception);
}
finally
{
document.Close();
}
return output.GetBuffer();
}
Problem:
I have byte array in my datatable.
each byte[] is single pdf file for one order.
I just want to all these pdf byte[] in a single byte[] for single file.
I just want to save it to the browser.
I can achieve appending the byte[], but it will create one byte[] data as pdf.
the following the sample i did here in console application actually I want in my web application.
here is my code:
public void NewPdf(string[] Pdf)
{
byte[] newPdf;
MemoryStream ms = new MemoryStream();
foreach (var onepdf in Pdf)
{
newPdf = System.IO.File.ReadAllBytes(onepdf);
//newPdf=System.Convert.FromBase64String(onepdf);
// int resultPdf = newPdf.Length;
// ms.Write(newPdf, 0, newPdf.Length);
// var ms = new MemoryStream(new byte[resultPdf], 0, resultPdf, true, true);
ms.Write(newPdf, 0, newPdf.Length);
//ms.Write(baadF00d, 0, baadF00d.Length);
//System.Buffer.BlockCopy(newPdf, 0, resultPdf, 0, newPdf.Length);
}
byte[] merged = ms.GetBuffer();
// File.WriteAllBytes("testpdf.pdf", merged);
PdfReader reader = new PdfReader(merged);
int n = reader.NumberOfPages;
Document document = new Document(reader.GetPageSizeWithRotation(1));
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream("thugs.pdf", FileMode.Create));
document.Open();
PdfContentByte cb = writer.DirectContent;
PdfImportedPage page;
int rotation;
int i = 0;
while (i < n)
{
i++;
document.SetPageSize(reader.GetPageSizeWithRotation(i));
document.NewPage();
page = writer.GetImportedPage(reader, i);
rotation = reader.GetPageRotation(i);
if (rotation == 90 || rotation == 270)
{
cb.AddTemplate(page, 0, -1f, 1f, 0, 0, reader.GetPageSizeWithRotation(i).Height);
}
else
{
cb.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
}
}
reader = new PdfReader(merged);
// we retrieve the total number of pages
n = reader.NumberOfPages;
document.Close();
}
Actually i am trying to do in asp.net mvc2....
i can return the byte[] in mvc2
return File(bytes, mimeType);
//the func merges the src pdf with the memory stream, wherein the stream may contain
//few othr src pdf streams in previous calls to this func
//in first cal, ms would be null
public static void MergePdf(MemoryStream ms, string srcFile)
{
PdfReader reader = new PdfReader(srcFile);
Document document = null;
PdfWriter writer = null;
int n = reader.NumberOfPages;
if (document == null)
{
document = new Document(reader.GetPageSizeWithRotation(1));
writer = PdfWriter.GetInstance(document, ms);
document.Open();
}
PdfContentByte cb = writer.DirectContent;
PdfImportedPage page;
int rotation;
int i = 0;
while (i < n)
{
i++;
document.SetPageSize(reader.GetPageSizeWithRotation(i));
document.NewPage();
page = writer.GetImportedPage(reader, i);
rotation = reader.GetPageRotation(i);
if (rotation == 90 || rotation == 270)
{
cb.AddTemplate(page, 0, -1f, 1f, 0, 0,
reader.GetPageSizeWithRotation(i).Height);
}
else
{
cb.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
}
}
}
I write the Memory stream, back to context.response.Outputstream; but the pdf doesnt load, the page 'Failed to load Pdf' results; Is there any problem in converting btwn memorystream and Pdf contents, or what may be the issue?
I had the same problem, and it turned out that the cause was not closing the document, and adding the following line of code:
document.Close();
should fix the problem.