itext7 PdfAConformanceException: Maximum array capacity is exceeded - c#

I am converting a text file of approx. 16K lines into a PDF/A-1b file. I get the exception "PdfAConformanceException: Maximum array capacity is exceeded". The document is generated with no problems if it is a normal PDF rather than a PDF/A. It happens only generating a PDF/A. The normal PDF document is about 1150 pages long. Any hint on how to solve this? The exception is generated in the "Doc.Close()" call.
This is the code that I use:
StreamReader str = new StreamReader(file_name);
PdfWriter writer = new PdfWriter(file_name.Replace(".txt", ".pdf"));
PdfDocument pdf = new PdfADocument(writer, PdfAConformanceLevel.PDF_A_1B, new PdfOutputIntent
("Custom", "", "https://www.color.org", "sRGB IEC61966-2.1",
new FileStream(INTENT, FileMode.Open, FileAccess.Read)));
Document doc = new Document(pdf);
pdf.SetTagged();
//Fonts need to be embedded
PdfFont font = PdfFontFactory.CreateFont(FONT, PdfEncodings.WINANSI, true);
Paragraph p = new Paragraph();
p.SetFont(font);
p.Add(str.ReadToEnd());
doc.Add(p);
doc.Close();
Thanks!

Related

How to get emoji to appear in the generated PDF using MigraDoc

I'm trying to generate a PDF that contains some emojis but with no success.
To make it simple and reproduce-able here is the code:
Document document = new Document();
Section section = document.AddSection();
Paragraph paragraph = section.AddParagraph();
paragraph.AddFormattedText("👀 😀 💨 ♡", new Font("Segoe UI Emoji"));
PdfDocumentRenderer pdfRenderer = new PdfDocumentRenderer(true);
pdfRenderer.Document = document;
pdfRenderer.RenderDocument();
var memoryStream = new MemoryStream();
var path = Path.GetTempFileName() + ".pdf";
pdfRenderer.PdfDocument.Save(path);
Process.Start(path);
But unfortunately empty rectangles appear instead:
��
This is a known limitation of PDFsharp. Surrogate pairs do not work yet and Unicode chars that require two 16-bit values (above 0xffff) will not show correctly.
See also:
https://github.com/empira/PDFsharp/issues/63

iText C#: Remove creation date

Is it possible to modify/remove the creation date in metadata? I'm looking to do something similar to this:
Overwrite creationDate in pdf using iText and pdf writer
EDIT:
I have tried the following methods:
writer.Info.Remove(PdfName.CREATIONDATE);
or
writer.Info.Put(PdfName.CREATIONDATE, new PdfDate(new DateTime(2017, 01, 01)));
where writer is a PdfWriter object.
However, that creates a copy of the object (a PdfDictionary) and doesn't modify the PDF I'm creating.
I also can't assign i.e. writer.Info = info
I tried following the advice given in the Java article.
I tried to do this:
var info = writer.Info;
stamper.MoreInfo = info
where stamper is a PdfStamper
But the types are incompatible and I don't think this would work. Does anyone know the actual methods to remove/modify the metadata?
EDIT 2:
Here is the code, I'm creating a new file from an existing PDF.
var filename = #"C:\Users\Someone\Documents\aPdf.pdf";
using( var output = new MemoryStream() )
{
Document document = new Document();
PdfCopy writer = new PdfCopy( document, output );
writer.CloseStream = false;
document.Open();
//read in PDF
PdfReader reader = new PdfReader(filename);
reader.ConsolidateNamedDestinations();
PdfImportedPage page = writer.GetImportedPage(reader, 1);
writer.AddPage(page);
reader.Close();
writer.Close();
document.Close();
return output.ToArray();
}
Now, when I open the file with a text editor this line is inserted (I need it constant/gone):
<</Producer(iTextSharp’ 5.5.12 ©2000-2017 iText Group NV \(AGPL-version\))/CreationDate(D:20180412155130+01'00')/ModDate(D:20180412155130+01'00')>>
The reason why we need to remove/set the date is that we're taking the MD5 hash of the file. Every time a new document is generated, that line changes leading to different MD5 hashes.
As I was trying to get a constant MD5 checksum for the generated file, I had to also set the ID constant, as mentioned by mkl.
My solution was to search byte array produced (i.e. the created PDF), and manually set the values to constants. The text is ASCII chars. I removed the /CreationDate and /ModifiedDated from the PDF entirely, and set the generated ID to a constant arbitrary value.

Flatten dynamic pdf using iTextSharp

I' m using itextsharp to create pdf from template pdf file. But new pdf file is created like dynamic pdf. I want to convert this file to static pdf file, so i tried to use xfaworker. I get "Signature was corrupted" error from itextsharp.licensekey.dll. How can i use xfaworker or another dll for flatten dynamic pdf?
public string Create(FaxPDFModel model, MemoryStream ms)
{
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
string templatePath = Path.GetDirectoryName(Uri.UnescapeDataString(uri.Path));
PdfReader pdfTemplate = new PdfReader(Path.Combine(Path.Combine(templatePath, "Docs"), "fax_template.pdf"));
PdfStamper stamper = new PdfStamper(pdfTemplate, ms);
stamper.Writer.CloseStream = false;
BaseFont bf = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, "ISO-8859-9", BaseFont.EMBEDDED);
var acroFields = stamper.AcroFields;
acroFields.GenerateAppearances = true;
stamper.FormFlattening = true;
acroFields.AddSubstitutionFont(bf);
acroFields.SetField("Name", "Mutabakat test");
acroFields.SetField("Title", "DANIÅžMANLIK");
acroFields.SetField("Department", "test");
acroFields.SetField("Phone", "0 (212) 555 55 55");
stamper.Close();
string path = Path.Combine(Path.Combine(templatePath, "Docs"), System.Guid.NewGuid().ToString());
string pdfPath = path + ".pdf";
Document document = new Document();
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(pdfPath, FileMode.Create));
XFAFlattener xfaf = new XFAFlattener(document, writer);
ms.Position = 0;
xfaf.Flatten(new PdfReader(ms));
document.Close();
return pdfPath;
}
If you want to solve your problem, you will have to start by fixing the following errors:
1. You are using code to fill AcroForms instead of code to fill XFA forms:
If you have a dynamic XFA form, your PDF acts as a container for XML. This form doesn't expect data in the form of key value pairs. This form expects data stored as XML.
You can not use this code:
var acroFields = stamper.AcroFields;
acroFields.AddSubstitutionFont(bf);
acroFields.SetField("Name", "Mutabakat test");
acroFields.SetField("Title", "DANIÅžMANLIK");
acroFields.SetField("Department", "test");
acroFields.SetField("Phone", "0 (212) 555 55 55");
This code expects that your form is an AcroForm. You need to fill the form like this:
AcroFields form = stamper.AcroFields;
XfaForm xfa = form.Xfa;
xfa.FillXfaForm(new FileStream(xml, FileMode.Open));
In this snippet xml refers to the data stored as XML.
2. You try to flatten the form before flattening the form:
I see this line in the first part of your code:
stamper.FormFlattening = true;
With this line, you remove all interactivity from your PDF. After closing the stamper object, you no longer have a form, hence the second part of your code will never work.
3. You are trying to embed a Standard Type 1 font:
This line doesn't make sense:
BaseFont bf = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, "ISO-8859-9", BaseFont.EMBEDDED);
Times-Roman is a Standard Type 1 font (in the old days, we called this a Base14 font); iText never embeds any of the 14 Standard Type 1 fonts defined for PDF, hence the parameter BaseFont.EMBEDDED will be ignored.
4. The real error:
XFA Worker is a closed source addon for iTextSharp. It requires a valid license key. When you get an error saying "Signature was corrupted", you are using a license key that is corrupt.
Possible causes:
You are not a customer of iText Group. You are using a key that you found somewhere and you changed some of its contents.
You are a customer of iText Group. You received a key, but somehow it got tampered with. In the past, we've had a similar problem where a customer was reading the key as if it was encoded in EBCDIC. Please contact your account manager at iText Group for more info.

Drawing on PDF using ITextSharp, without creating a new PDF

i try to draw simple shapes (rectangles, circles..) on an existing PDF using ITextSharp, without having to create a new PDF. I found a post who talk about this issue (itextsharp modify existing pdf (no new source pdf) and add watermark) and i would like to know if anybody could tell me more about it.
my aim is to modify a pdf by adding a circle on it, the current solution involve the creation of a new PDF (Itextsharp). Is it possible to add a circle on a PDF without creating a new one ?
Thank you.
J.
You can't read a file and write to it simultaneously. Think of how Word works: you can't open a Word document and write directly to it. Word always creates a temporary file, writes the changes to it, then replaces the original file with it and then throws away the temporary file.
You can do that too:
read the original file with PdfReader,
create a temporary file for PdfStamper, and when you're done,
replace the original file with the temporary file.
Or:
read the original file into a byte[],
create PdfReader with this byte[], and
use the path to the original file for PdfStamper.
This second option is more dangerous, as you'll lose the original file if you do something that causes an exception in PdfStamper.
As for adding content with PdfStamper, please take a look at the section entitled "Manipulating existing PDFs" in the free ebook The Best iText Questions on StackOverflow. You'll find questions such as:
How to add a watermark to a PDF file?
How do I insert a hyperlink to another page with iTextSharp in an existing PDF?
iText - How to stamp image on existing PDF and create an anchor
...
All of these examples add content by creating a PdfContentByte instance like this:
PdfContentByte canvas = stamper.getOverContent(pagenumber);
It's this canvas you need to use when drawing a circle on the page with page number pagenumber. It is important that you use the correct coordinates when you do this. That's explained here: How to position text relative to page using iText?
Update:
Json posted the following code in the comments:
string oldFile = #"C:\Users\ae40394\Desktop\hello.pdf";
string newFile = #"C:\Users\ae40394\Desktop\NEW.pdf";
// creating a reader with the original PDF
PdfReader reader = new PdfReader(oldFile);
Rectangle rect = reader.GetPageSize(1);
FileStream fs = new FileStream(newFile,FileMode.Create);
using (PdfStamper stamper = new PdfStamper(reader, fs)) {
// modify the pdf content
PdfContentByte cb = stamper.GetOverContent(1);
cb.SetColorStroke(iTextSharp.text.BaseColor.GREEN);
cb.SetLineWidth(5f);
cb.Circle(rect.GetLeft() + 30, rect.GetBottom() + 30 ,20f);
cb.Stroke();
}
reader.Close();
File.Replace(#"C:\Users\ae40394\Desktop\NEW.pdf", #"C:\Users\ae40394\Desktop\hello.pdf", #"C:\Users\ae40394\Desktop\hello.pdf.bac");
I slightly adapted the code, because:
There is no need for a Document object,
The stamper is closed when using is closed,
When the stamper is closed, so is the FileStream
the coordinates of the circle were hard coded. I used the page size to make sure they are made relative to the origin of the coordinate system, although to be sure, you may also want to check if there's a Crop Box.
You CAN read a file and write to it simultaneously.
Here is an example:
private void button4_Click(object sender, EventArgs e)
{
using (PdfReader pdfReader = new PdfReader(new FileStream(pdfInput, FileMode.Open, FileAccess.Read, FileShare.Read)))
{
using (PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(pdfInput, FileMode.Open, FileAccess.Write, FileShare.None)))
{
PdfContentByte canvas = pdfStamper.GetUnderContent(1);
canvas.SetColorFill(BaseColor.YELLOW);
canvas.Rectangle(36, 786, 66, 16);
canvas.Fill();
}
}
// PDF Datei im Anschluss anzeigen/öffnen
System.Diagnostics.Process.Start(pdfInput);
}
string oldFile = #"C:\...6166-21.pdf";
string newFile = #"C:\...NEW.pdf";
// open the reader
PdfReader reader = new PdfReader(oldFile);
Rectangle size = reader.GetPageSizeWithRotation(1);
Document document = new Document(size);
FileStream fs = new FileStream(newFile, FileMode.Create, FileAccess.Write);
PdfWriter writer = PdfWriter.GetInstance(document, fs);
document.Open();
// the pdf content
PdfContentByte cb = writer.DirectContent;
cb.SetColorStroke(iTextSharp.text.BaseColor.GREEN);
cb.Circle(150f, 150f, 50f);
cb.Stroke();
// 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();

Export arabic data into pdf asp.net showing error

When I export ARABIC data into pdf.Microsoft adobereader showing error.Adobe reader could not open file because it is either not a supported file.My code is following asp.net c#.Guide me
protected void btnExport_Click(object sender, EventArgs e)
{
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=TestPage.pdf");
Document doc = new Document(PageSize.LETTER);
doc.Open();
//Sample HTML
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(#"<p>This is a test: <strong>مسندم</strong></p>");
//Path to our font
string arialuniTff = Server.MapPath("~/tradbdo.TTF");
//Register the font with iTextSharp
iTextSharp.text.FontFactory.Register(arialuniTff);
//Create a new stylesheet
iTextSharp.text.html.simpleparser.StyleSheet ST = new iTextSharp.text.html.simpleparser.StyleSheet();
//Set the default body font to our registered font's internal name
ST.LoadTagStyle(HtmlTags.BODY, HtmlTags.FACE, "Traditional Arabic Bold");
//Set the default encoding to support Unicode characters
ST.LoadTagStyle(HtmlTags.BODY, HtmlTags.ENCODING, BaseFont.IDENTITY_H);
//Parse our HTML using the stylesheet created above
List<IElement> list = HTMLWorker.ParseToList(new StringReader(stringBuilder.ToString()), ST);
//Loop through each element, don't bother wrapping in P tags
foreach (var element in list)
{
doc.Add(element);
}
doc.Close();
Response.Write(doc);
Response.End();
}
I found the following article which shows how to correctly export and display Arabic content via the iTextSharp library: http://geekswithblogs.net/JaydPage/archive/2011/11/02/using-itextsharp-to-correctly-display-hebrew--arabic-text-right.aspx.
Here is the code sample that you can try:
using iTextSharp.text;
using iTextSharp.text.pdf;
using System.Text.RegularExpressions;
using System.IO;
using System.Diagnostics;
public void WriteDocument()
{
//Declare a itextSharp document
Document document = new Document(PageSize.A4);
//Create our file stream and bind the writer to the document and the stream
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(#"C:\Test.Pdf", FileMode.Create));
//Open the document for writing
document.Open();
//Add a new page
document.NewPage();
//Reference a Unicode font to be sure that the symbols are present.
BaseFont bfArialUniCode = BaseFont.CreateFont(#"C:\ARIALUNI.TTF", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
//Create a font from the base font
Font font = new Font(bfArialUniCode, 12);
//Use a table so that we can set the text direction
PdfPTable table = new PdfPTable(1);
//Ensure that wrapping is on, otherwise Right to Left text will not display
table.DefaultCell.NoWrap = false;
//Create a regex expression to detect hebrew or arabic code points
const string regex_match_arabic_hebrew = #"[\u0600-\u06FF,\u0590-\u05FF]+";
if (Regex.IsMatch("مسندم", regex_match_arabic_hebrew, RegexOptions.IgnoreCase))
{
table.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
}
//Create a cell and add text to it
PdfPCell text = new PdfPCell(new Phrase("مسندم", font));
//Ensure that wrapping is on, otherwise Right to Left text will not display
text.NoWrap = false;
//Add the cell to the table
table.AddCell(text);
//Add the table to the document
document.Add(table);
//Close the document
document.Close();
//Launch the document if you have a file association set for PDF's
Process AcrobatReader = new Process();
AcrobatReader.StartInfo.FileName = #"C:\Test.Pdf";
AcrobatReader.Start();
}
The iTextSharp.text.Document is a class used to help bridge human concepts like Paragraph and Margin into PDF concepts. The bridge part is important. It is not a PDF file in any way so it should never be treated as a PDF. Doing so would be like treating System.Drawing.Graphics as if it were an image. This leads to one of your problems on the second to last line of code that tries to treat the Document as if it were a PDF by sending it directly to the output stream:
//This won't work
Response.Write(doc);
You will find many, many tutorials out there that do this and they are all wrong. Fortunately (or unfortunately), PDF is forgiving and allows junk data at the end so only a handful of PDF fail and people assume there was some other problem.
Your other problem is that you are missing a PdfWriter. If Document is the bridge, PdfWriter is the actual construction worker that puts that PDF together. It, however, is also not a PDF. Instead, it needs to be bound to a stream like a file, in-memory or the HttpResponse.OutputStream.
Below is some code that shows this off. I very strongly recommend separating your PDF logic from your ASPX logic. Do all of you PDF stuff first and get an actual "something" that represents a PDF, then do something with it.
At the beginning we declare a byte array that we'll fill in later. Next we create a System.IO.MemoryStream that will be used to write the PDF to. After creating the Document we then create a PdfWriter that's bound to the Document and our stream. Your internal code is the same and although I didn't test it it appears correct. Right before we're done with our MemoryStream we grab the active bytes into our byte array. Lastly we use the BinaryWrite() method to send our raw binary PDF to the requesting client.
//At the end of this bytes will hold a byte array representing an actual PDF file
Byte[] bytes;
//Create a simple in-memory stream
using (var ms = new MemoryStream()){
using (var doc = new Document()) {
//Create a new PdfWriter bound to our document and the stream
using (var writer = PdfWriter.GetInstance(doc, ms)) {
doc.Open();
//This is unchanged from the OP's code
//Sample HTML
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(#"<p>This is a test: <strong>مسندم</strong></p>");
//Path to our font
string arialuniTff = Server.MapPath("~/tradbdo.TTF");
//Register the font with iTextSharp
iTextSharp.text.FontFactory.Register(arialuniTff);
//Create a new stylesheet
iTextSharp.text.html.simpleparser.StyleSheet ST = new iTextSharp.text.html.simpleparser.StyleSheet();
//Set the default body font to our registered font's internal name
ST.LoadTagStyle(HtmlTags.BODY, HtmlTags.FACE, "Traditional Arabic Bold");
//Set the default encoding to support Unicode characters
ST.LoadTagStyle(HtmlTags.BODY, HtmlTags.ENCODING, BaseFont.IDENTITY_H);
//Parse our HTML using the stylesheet created above
List<IElement> list = HTMLWorker.ParseToList(new StringReader(stringBuilder.ToString()), ST);
//Loop through each element, don't bother wrapping in P tags
foreach (var element in list) {
doc.Add(element);
}
doc.Close();
}
}
//Right before closing the MemoryStream grab all of the active bytes
bytes = ms.ToArray();
}
//We now have a valid PDF and can do whatever we want with it
//In this case, use BinaryWrite to send it directly to the requesting client
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=TestPage.pdf");
Response.BinaryWrite(bytes);
Response.End();

Categories

Resources