I am adding footer text to existing BYTES in each page using the code shown below, which is visible in Chrome as well as in Foxit PhantomPDF, however, it's not visible in Adobe PDF reader.
In addition to the footer, I also add headers which are visible even with Adobe.
private byte[] AddPageHeaderFooter(byte[] pdf, float marginLeft, float marginRight, float marginTop,
float marginBottom, DataSet prospectDetails, ref int startingPageNumber, string logoPath, bool isLandscape = false)
{
var dataRow = prospectDetails.Tables[0].Rows[0];
var prospectDate = Convert.ToDateTime(dataRow[0]);
using (var stream = new MemoryStream())
{
stream.Write(pdf, 0, pdf.Length);
var reader = new PdfReader(pdf);
var document = new Document(reader.GetPageSizeWithRotation(1), marginLeft, marginRight, marginTop,
marginBottom);
var writer = PdfWriter.GetInstance(document, stream);
document.Open();
var contentByte = writer.DirectContent;
var pageIndex = startingPageNumber;
for (var page = 1; page <= reader.NumberOfPages; page++)
{
document.NewPage();
pageIndex++;
var importedPage = writer.GetImportedPage(reader, page);
if (isLandscape)
contentByte.AddTemplate(importedPage, 0, -1f, 1f, 0, 0,
reader.GetPageSizeWithRotation(page).Height);
else
contentByte.AddTemplate(importedPage, 0, 0);
contentByte.BeginText();
var baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
// Code to add header
// Footer
// Not visible parts **START**
contentByte.SetFontAndSize(baseFont, 7);
var prospectDateString = string.Format("{0:ddd, MMM d, yyyy}", prospectDate);
contentByte.ShowTextAligned(PdfContentByte.ALIGN_CENTER,
"FOOTER LINE 1",
isLandscape ? 398 : 305f, 50, 0);
contentByte.ShowTextAligned(PdfContentByte.ALIGN_CENTER,
"FOOTER LINE 2", isLandscape ? 398 : 305f, 42, 0);
contentByte.ShowTextAligned(PdfContentByte.ALIGN_LEFT,
prospectDateString.Substring(5, prospectDateString.Length - 5), document.Left, marginBottom, 0);
contentByte.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "- " + pageIndex + " -",
isLandscape ? 398 : 305f, marginBottom, 0);
contentByte.ShowTextAligned(PdfContentByte.ALIGN_RIGHT, string.Format("{0:T}", prospectDate),
document.Right, marginBottom, 0);
contentByte.EndText();
contentByte.SaveState();
// Not visible parts **END**
// Footer line
// Not visible parts **START**
contentByte.SetColorStroke(new PdfSpotColor("black", new BaseColor(0, 0, 0)), 100);
contentByte.SetLineWidth(0.25f);
contentByte.Rectangle(marginLeft, 58, isLandscape ? 732 : 552, 0.25f);
contentByte.FillStroke();
// Not visible parts **END**
contentByte.RestoreState();
}
startingPageNumber = pageIndex;
document.Close();
return stream.ToArray();
}
}
Issue:
Only the footer line that I draw is visible in Adobe.
Footer texts namely, footer line 1, footer line 2, Date as well as page number is not visible even when I try to print the document.
Screenshot:
Related
I am not sure how to add this text to the canvas in iText7. In the old version I use this BaseFont.CreateFont and overContent. In iText7 I see this PdfCanvas control and this PdfCanvas.BeginText mehtod but I am getting a error related to no overoad.
PdfPage pdfPage = pdfDocument.GetPage(i);
Rectangle pageSizeWithRotation = pdfPage.GetPageSizeWithRotation();
PdfCanvas canvas = new PdfCanvas(pdfPage);
Text pdfText = new Text(disclaimerText)
.SetFontColor(ColorConstants.BLACK)
.SetFont(PdfFontFactory.CreateFont(StandardFonts.HELVETICA, "Cp1250"))
.SetFontSize(7F);
canvas.BeginText(pdfText);
Old Version I have something like this
PdfContentByte overContent = pdfStamper.GetOverContent(i);
overContent.BeginText();
BaseFont baseFont = BaseFont.CreateFont("Helvetica", "Cp1250", false);
overContent.SetFontAndSize(baseFont, 7F);
overContent.SetRGBColorFill(0, 0, 0);
float n2 = 15F;
float n3 = pageSizeWithRotation.Height - 10F;
overContent.ShowTextAligned(0, disclaimerText, n2, n3, 0F);
overContent.EndText();
You can refer to the following code to understand how the BeginText and EndText work together with PdfCanvas.
//Get the page from the pdf
PdfPage page = pdfDoc.GetPage(i);
Rectangle pageSize = page.GetPageSizeWithRotation();
int pageNumber = pdfDoc.GetPageNumber(page);
PdfCanvas pdfCanvas = new PdfCanvas(page.NewContentStreamBefore(), page.GetResources(), pdfDoc);
//Set background
Color limeColor = new DeviceCmyk(0.208 f, 0, 0.584 f, 0);
Color blueColor = new DeviceCmyk(0.445 f, 0.0546 f, 0, 0.0667 f);
pdfCanvas.SaveState()
.SetFillColor(pageNumber % 2 == 1 ? limeColor : blueColor)
.Rectangle(pageSize.GetLeft(), pageSize.GetBottom(),
pageSize.GetWidth(), pageSize.GetHeight())
.Fill()
.RestoreState();
//Add header and footer
pdfCanvas.BeginText()
.SetFontAndSize(PdfFontFactory.CreateFont(StandardFonts.HELVETICA), 9)
.MoveText(pageSize.GetWidth() / 2 - 60, pageSize.GetTop() - 20)
.ShowText("THE TRUTH IS OUT THERE")
.MoveText(60, -pageSize.GetTop() + 30)
.ShowText(pageNumber.ToString())
.EndText();
//Add watermark
iText.Layout.Canvas canvas = new iText.Layout.Canvas(pdfCanvas, pdfDoc, page.GetPageSize());
canvas.SetProperty(Property.FONT_COLOR, Color.WHITE);
canvas.SetProperty(Property.FONT_SIZE, 60);
canvas.SetProperty(Property.FONT, PdfFontFactory.CreateFont(StandardFonts.HELVETICA_BOLD));
canvas.ShowTextAligned(new Paragraph("CONFIDENTIAL"), 298, 421, pdfDoc.GetPageNumber(page), TextAlignment.CENTER, VerticalAlignment.MIDDLE, 45);
pdfCanvas.Release();
This example is also available here in the knowledge base of iText 7 at https://kb.itextpdf.com/home/it7kb/examples/itext-7-jump-start-tutorial-chapter-3 example "c03e03_ufo"
I need to develop class, which should have a method to add text to page (with different parameters) and this method can be called many times and in result user of class can call a method to get PDF.
My code:
public class PdfActions : IPdfActions, IDisposable
{
PdfReader pdfReader;
MemoryStream ms = new MemoryStream();
PdfWriter outputWriter;
Document inputDoc;
int pageCount;
public PdfActions(byte[] input)
{
pdfReader = new PdfReader(input);
pageCount = pdfReader.NumberOfPages;
// load the input document
inputDoc = new Document(pdfReader.GetPageSizeWithRotation(1));
outputWriter = PdfWriter.GetInstance(inputDoc, ms);
inputDoc.Open();
for (int i = 1; i <= pageCount; i++)
{
inputDoc.SetPageSize(pdfReader.GetPageSizeWithRotation(i));
inputDoc.NewPage();
PdfContentByte cb = outputWriter.DirectContent;
PdfImportedPage page = outputWriter.GetImportedPage(pdfReader, i);
cb.AddTemplate(page, 0, 0);
}
}
it's constructor, which "copy" PDF to stream
Then my method to add text:
public void AddText(string text, BaseColor color, float x, float y, float fontSize = 12, string font = iTextSharp.text.pdf.BaseFont.HELVETICA, int alignment = 3, int activePage = 1)
{
PdfContentByte cb = outputWriter.DirectContent;
BaseFont bf = BaseFont.CreateFont(font, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
cb.SetColorFill(color);
cb.SetFontAndSize(bf, fontSize);
// write the text in the pdf content
cb.BeginText();
// put the alignment and coordinates here
cb.ShowTextAligned(alignment, text, x, y, 0);
cb.EndText();
PdfImportedPage page = outputWriter.GetImportedPage(pdfReader, activePage);
cb.AddTemplate(page, 0, 0);
}
and method to get PDF byte array:
public byte[] GetPdfOutput()
{
inputDoc.Close();
outputWriter.Close();
return ms.ToArray();
}
I call it:
_pdfActions = new PdfActions(bytes);
_pdfActions.AddText("Example, Inc.", BaseColor.Black, x: 185, y: 380, fontSize: 26, font: iTextSharp.text.pdf.BaseFont.TIMES_ROMAN);
_pdfActions.AddText("My Address", BaseColor.Black, x: 185, y: 360, fontSize: 16, font: iTextSharp.text.pdf.BaseFont.TIMES_ROMAN);
var result = _pdfActions.GetPdfOutput();
But it always PDF as template. What is wrong?
PS. I was implemented method AddText as incapsulated (with open stream/actions/close stream), but it does not work with many actions.
I'm signing a document with token certificate:
var cp = new Org.BouncyCastle.X509.X509CertificateParser();
var chain = new[] { cp.ReadCertificate(cert.RawData) };
var externalSignature = new X509Certificate2Signature(cert, "SHA-1");
var pdfReader = new PdfReader(origem);
var signedPdf = new FileStream(destino, FileMode.Create);
var pdfStamper = PdfStamper.CreateSignature(pdfReader, signedPdf, '\0');
var sig = pdfStamper.SignatureAppearance;
sig.SetVisibleSignature(new Rectangle(50, 0, 500, 50), pdfReader.NumberOfPages, "Signature");
sig.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.DESCRIPTION;
sig.Layer2Text = "Assinado digitalmente por " + cert.SubjectName.Name;
sig.Layer2Font = new Font(Font.FontFamily.TIMES_ROMAN, 7);
MakeSignature.SignDetached(sig, externalSignature, chain, null, null, null, 0, CryptoStandard.CMS);
The signature text is rendered at bottom of the page. How can I change to a vertical mode, in the right part of document, outside the content margins?
thanks
First of all, to get some vertically oriented signature, the rectangle in which to visualize the signature should be somewhat more vertically oriented. Thus, in place of your
sig.SetVisibleSignature(new Rectangle(50, 0, 500, 50), pdfReader.NumberOfPages, "Signature");
you should use something like
sig.SetVisibleSignature(new Rectangle(50, 0, 50, 500), pdfReader.NumberOfPages, "Signature");
Now you clarified in comments that not only the visualization rectangle should have a vertical orientation but that the text also should be drawn vertically. iText by default creates visualizations with horizontal text. Thus, you have to use customized appearances.
As I am more at home with iText/Java, this example to customize a PdfSignatureAppearance appearance is in Java. It should be easy to transform to iTextSharp/C#, though.
appearance.setVisibleSignature(rectangle, PAGENUMBER, SIGNATURENAME);
// customize appearance layer 2 to display text vertically
PdfTemplate layer2 = appearance.getLayer(2);
layer2.transform(new AffineTransform(0, 1, -1, 0, rectangle.getWidth(), 0));
Font font = new Font();
font.setColor(BaseColor.WHITE);
font.setSize(10);
ColumnText ct2 = new ColumnText(layer2);
ct2.setRunDirection(PdfWriter.RUN_DIRECTION_NO_BIDI);
ct2.setSimpleColumn(new Phrase("Signed by me, myself and I", font), 0, 0, rectangle.getHeight(), rectangle.getWidth(), 15, Element.ALIGN_CENTER);
ct2.go();
This example draws "Signed by me, myself and I" vertically in the page area rectangle.
public bool drawVerticalText(string _text, Color _color, int _angle, int _size, int _left, int _top)
{
try
{
BaseColor bc = new BaseColor(_color.R, _color.G, _color.B, _color.A);
PdfContentByte cb = writer.DirectContent;
BaseFont bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED);
//int width = baseFont.GetWidth(_text);
cb.BeginText();
cb.SetColorFill(CMYKColor.RED);
cb.SetFontAndSize(bf, _size);
cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, _text, _left, document.Top - _top, _angle);
cb.EndText();
document.Close();
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return false;
}
}
You can change the alpha value of the color, rotation angle (say, 45), text size and make a watermark to your document...
While above method uses DirectContent with absolute coordinates, the below method uses cell object with rotation property. Note that cell rotation can be multiple of 90, while with the 1st method you can have any angle...
public void drawVerticalText2()
{
PdfPTable table = new PdfPTable(4);
float[] widths = new float[] { 1.25f, 1.55f, 0.35f, 0.35f };
table.SetWidths(widths);
PdfPCell horizontalCell = new PdfPCell(new Phrase("I'm horizontal"));
horizontalCell.Border = BORDERS.BOX;
horizontalCell.HorizontalAlignment = 1;
table.AddCell(horizontalCell);
PdfPCell horizontalMirroredCell = new PdfPCell(new Phrase("I'm horizontal mirrored"));
horizontalMirroredCell.Border = BORDERS.BOX;
horizontalMirroredCell.HorizontalAlignment = 1;
horizontalMirroredCell.Rotation = 180;
table.AddCell(horizontalMirroredCell);
PdfPCell verticalCell = new PdfPCell(new Phrase("I'm vertical"));
verticalCell.Border = BORDERS.BOX;
verticalCell.HorizontalAlignment = 1;
verticalCell.Rotation = 90;
table.AddCell(verticalCell);
PdfPCell verticalMirroredCell = new PdfPCell(new Phrase("I'm vertical mirrored"));
verticalMirroredCell.Border = BORDERS.BOX;
verticalMirroredCell.HorizontalAlignment = 1;
verticalMirroredCell.Rotation = -90;
table.AddCell(verticalMirroredCell);
table.SpacingBefore = 20f;
table.SpacingAfter = 30f;
document.Add(table);
document.Close();
}
enjoy!
I have pdf files exported as legal format and want to convert them to letter format (basically shrink them), each file may have 1 to 3 pages, below is the code I tried but I have these problems:
the page size is reduced which is good, but I can't use the margin properties to put the page at the correct borders of the container (the page I kind of shrinked but drawn somewhere at the bottom of the resulted pdf file)
I couldn't increment the number of pages so the code draws both pages, one on top of the other.
Here's the code
PdfImportedPage page;
PdfReader reader = new PdfReader(#"C:\pdf\legalFormat.pdf");
Document doc = new Document(PageSize.A4, 0, 0, 0, 0);
PdfWriter writer = PdfWriter.GetInstance(doc, new FileStream(#"C:\pdf\letterFormat.PDF", FileMode.Create));
doc.Open();
PdfContentByte cb = writer.DirectContent;
for (int i = 1 ; i < reader.NumberOfPages + 1; i++){
page = writer.GetImportedPage(reader, i); // i is the number of page
float Scale = 0.67f;
cb.AddTemplate(page, Scale, 0, 0, Scale, 0, 0);
}
doc.Close();
Problem solved:
in a main proc run this for test.
string original = args[0];
string inPDF = original;
string outPDF = Directory.GetDirectoryRoot(original) + "temp.pdf";
PdfReader pdfr = new PdfReader(inPDF);
Document doc = new Document(PageSize.LETTER);
Document.Compress = true;
PdfWriter writer = PdfWriter.GetInstance(doc, new FileStream(outPDF, FileMode.Create));
doc.Open();
PdfContentByte cb = writer.DirectContent;
PdfImportedPage page;
for (int i = 1; i < pdfr.NumberOfPages + 1; i++)
{
page = writer.GetImportedPage(pdfr, i);
cb.AddTemplate(page, PageSize.LETTER.Width / pdfr.GetPageSize(i).Width, 0, 0, PageSize.LETTER.Height / pdfr.GetPageSize(i).Height, 0, 0);
doc.NewPage();
}
doc.Close();
//just renaming, conversion / resize process ends at doc.close() above
File.Delete(original);
File.Copy(outPDF, original);
Hi
I want to add a text in persian language (a right to left language) to the top of an existing pdf file, using iTextSharp Version 5.0.0.0 library.
I use this code:
public static void InsertText(string SourceFileName, string TargetFileName, string Text, int x, int y)
{
PdfReader reader = new PdfReader(SourceFileName);
Document document = new Document(PageSize.A4, 0, 0, 0, 0); // open the writer
FileStream fs = new FileStream(TargetFileName, FileMode.Create, FileAccess.Write);
PdfWriter writer = PdfWriter.GetInstance(document, fs);
document.Open();
PdfContentByte cb = writer.DirectContent; // select the font properties
FontFactory.RegisterDirectories();
Font fTahoma = FontFactory.GetFont("Tahoma", BaseFont.IDENTITY_H, 10, Font.NORMAL, BaseColor.RED);
writer.SetMargins(0, 0, 0, 0);
ColumnText ct = new ColumnText(writer.DirectContent);
ct.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
Phrase p = new Phrase(Text, fTahoma);
ct.SetText(p);
ct.SetSimpleColumn(x, y, x + 350, y + 20);
ct.Go();
for (int i = 1; i <= reader.NumberOfPages; i++)
{
PdfImportedPage page = writer.GetImportedPage(reader, i);
cb.AddTemplate(page, 0, 0); // close the streams and voilá the file should be changed :)
document.NewPage();
}
document.Close();
fs.Close();
writer.Close();
}
I call InsertText("Source.pdf", "Target.pdf", "Persian message", 10, 800);
My source.pdf page size is: height: 842, width: 595
Unfortunately i get target.pdf with only half of my message! The other vertical half is hidden!
Now the question is: How i can add a right to left language text to the top of an existing pdf file?
Problem: The imported page is probably overwriting the text.
Solution: Add your PdfImportedPage, THEN add the text.