Insert pages into PDF - pdf

Is there any function like Document.InsertPage(pageIndex)? Or any alternative solution?

What you are looking for is PdfStamper.insertPage(int, Rectangle).
See a full example of how to use it here, but in short, it should boil down to:
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
stamper.insertPage(pageIndex, reader.getPageSizeWithRotation(1));
// insert content via stamper.getUnderContent() or stamper.getOverContent()
stamper.close();
reader.close();
Note that this is Java code, but the C# counterpart can be deduced quite easily.

Related

what will be the alternative for Pdfstamper in itext7?

I tried to find the alternative for Pdfstamper in itext7 but didn't get how to use? I've already implemented code in itextshap its working but not in itext7.
I've one more doubt what will be the alternative for Acro Fields in itext7?
public byte[] GeneratePDF(string pdfPath, Dictionary<string, string> formFieldMap, bool formFlattening = true)
{
var output = new MemoryStream();
var reader = new PdfReader(pdfPath);
var stamper = new PdfStamper(reader, output);
//PdfDocument pdfDocument = new PdfDocument(reader, writer);
var formFields = stamper.AcroFields;
foreach (var fieldName in formFieldMap.Keys)
formFields.SetField(fieldName, formFieldMap[fieldName]);
stamper.FormFlattening = formFlattening;
stamper.Close();
reader.Close();
return output.ToArray();
}
The iText API got completely overhauled between versions 5.x and 7.x. Thus, you do not always have a one-to-one correspondence between classes here and there. Thus, I would propose studying the introductory ebooks on the iText knowledge base site before porting code.
There actually is an example in those ebooks very similar to your code:
//Initialize PDF document
PdfDocument pdf = new PdfDocument(new PdfReader(src), new PdfWriter(dest));
PdfAcroForm form = PdfAcroForm.GetAcroForm(pdf, true);
IDictionary<String, PdfFormField> fields = form.GetFormFields();
PdfFormField toSet;
fields.TryGetValue("name", out toSet);
toSet.SetValue("James Bond");
fields.TryGetValue("language", out toSet);
toSet.SetValue("English");
fields.TryGetValue("experience1", out toSet);
toSet.SetValue("Off");
fields.TryGetValue("experience2", out toSet);
toSet.SetValue("Yes");
fields.TryGetValue("experience3", out toSet);
toSet.SetValue("Yes");
fields.TryGetValue("shift", out toSet);
toSet.SetValue("Any");
fields.TryGetValue("info", out toSet);
toSet.SetValue("I was 38 years old when I became an MI6 agent.");
form.FlattenFields();
pdf.Close();
("Flattening a Form" in "Chapter 4: Making a PDF interactive | .NET" of "iText 7: Jump-Start Tutorial for .NET")

NullPointerException when decrypting pdf with itext

We are decrypting a pdf file with itext 5.5.8. The source code is as follows:
FileOutputStream outputstream = new FileOutputStream(outfile);
PDFReader reader = new PdfReader(new FileInputStream(infile), password.getBytes());
PDFStamper stamper = new PdfStamper(reader, outputstream);
stamper.close();
reader.close();
At the end I get the following exception:
java.lang.NullPointerException
at com.itextpdf.text.pdf.StandardDecryption.finish(StandardDecryption.java:102)
at com.itextpdf.text.pdf.PdfEncryption.decryptByteArray(PdfEncryption.java:776)
at com.itextpdf.text.pdf.PdfReader.getStreamBytesRaw(PdfReader.java:2634)
at com.itextpdf.text.pdf.PdfReader.getStreamBytesRaw(PdfReader.java:2650)
at com.itextpdf.text.pdf.PRStream.toPdf(PRStream.java:230)
at com.itextpdf.text.pdf.PdfIndirectObject.writeTo(PdfIndirectObject.java:158)
at com.itextpdf.text.pdf.PdfWriter$PdfBody.write(PdfWriter.java:403)
at com.itextpdf.text.pdf.PdfWriter$PdfBody.add(PdfWriter.java:381)
at com.itextpdf.text.pdf.PdfWriter.addToBody(PdfWriter.java:870)
at com.itextpdf.text.pdf.PdfStamperImp.close(PdfStamperImp.java:434)
at com.itextpdf.text.pdf.PdfStamperImp.close(PdfStamperImp.java:409)
at com.itextpdf.text.pdf.PdfStamper.close(PdfStamper.java:231)
The same pdf (PDF-1.4) file can be decrypted with itext version 2.1.7.5. With this we've never had any problem.
Am I missing something? Can this problem be solved in a simple way?

Returning PDFDocument object from PDFStamper itextsharp

I want to return the Document object from below code.
At present I get a document has no pages exception.
private static Document GeneratePdfAcroFields(PdfReader reader, Document docReturn)
{
if (File.Exists(System.Configuration.ConfigurationSettings.AppSettings["TEMP_PDF"]))
File.Delete(System.Configuration.ConfigurationSettings.AppSettings["TEMP_PDF"]);
PdfStamper stamper = new PdfStamper(reader, new FileStream(System.Configuration.ConfigurationSettings.AppSettings["TEMP_PDF"],FileMode.Create));
AcroFields form = stamper.AcroFields;
///INSERTING TEXT DYNAMICALLY JUST FOR EXAMPLE.
form.SetField("topmostSubform[0].Page16[0].topmostSubform_0_\\.Page78_0_\\.TextField3_9_[0]", "This value was dynamically added.");
stamper.FormFlattening = false;
stamper.Close();
FileStream fsRead = new FileStream(System.Configuration.ConfigurationSettings.AppSettings["TEMP_PDF"], FileMode.Open);
Document docret = new Document(reader.GetPageSizeWithRotation(1));
return docret;
}
Thanks Chris.
Just to reiterate what #BrunoLowagie is saying, passing Document objects around almost never makes >sense. Despite what the name might sound like, a Document doesn't represent a PDF in any way. Calling >ToString() or GetBytes() (if that method actually existed) wouldn't get you a PDF. A Document is just a >one-way funnel for passing human-friendly commands over to an engine that actually writes raw PDF >tokens. The engine, however, is also not even a PDF. The only thing that truly is a PDF is the raw >bytes of the stream that is being written to. – Chris Haas

iTextSharp filling forms and creating multiple pages

I have following written codes
Dim template As String = Server.MapPath("files/") & "2_paged_form.pdf"
Dim newFile As String = Server.MapPath("exports/") & "newFile.pdf"
Dim reader = New PdfReader(template)
Dim output = New FileStream(newFile, FileMode.Create, FileAccess.Write)
Dim stamp = New PdfStamper(reader, output)
stamp.AcroFields.SetField("client", "hello")
stamp.AcroFields.SetField("name", "test test")
stamp.AcroFields.SetField("address", "Hellocourt")
stamp.AcroFields.SetField("postcode", "xx 3xx")
stamp.AcroFields.SetField("dob", "11/02/1987")
stamp.FormFlattening = True
stamp.Close()
output.Close()
reader.Close()
I have managed to created a newfile.pdf with only onetime entry from 2_paged_form.pdf.
However I have multiple information to loop through so that newfile.pdf has multiple entries. for example newfile.pdf should have 10 pages with 5 different entries.
Could anyone help?
This is documented on the official iText site and in the book.
If you prefer watching a video, you can watch this tutorial. You can try the examples here. You need the entry "Fill, Flatten and Merge: how to do it correctly." The code for these examples can be found here: FillFlattenMerge2. Note that there's also a FillFlattenMerge1 example that demonstrates how NOT to do it. Please don't use that example ;-)
If you prefer reading a book, please download Chapter 6 of "iText in Action - Second Edition". You already know how to fill out one form (as described on page 185), you now want to merge different results. Again, there's an example on how not to do it (on page 190) and on how you should do it (on page 190-191).
I have never written a line of vb.net, but please look at this Java code as if it were pseudo code:
PdfCopy copy = new PdfSmartCopy(document, new FileOutputStream(dest));
document.open();
ByteArrayOutputStream baos;
PdfReader reader;
PdfStamper stamper;
AcroFields fields;
while (data.hasMoreElements()) {
// create a PDF in memory
baos = new ByteArrayOutputStream();
reader = new PdfReader(SRC);
stamper = new PdfStamper(reader, baos);
fields = stamper.getAcroFields();
MyData myData = data.nextElement();
fields.setField("name", myData.getName());
fields.setField("address", myData.getAddress());
...
stamper.setFormFlattening(true);
stamper.close();
reader.close();
// add the PDF to PdfCopy
reader = new PdfReader(baos.toByteArray());
copy.addDocument(reader);
reader.close();
}
document.close();
As you can see, you need to create to fill the form resulting in a PDF that is kept in memory. Then you need to read this PDF from memory and add it to a PdfSmartCopy instance using the addDocument() method.
P.S. 1: What is wrong with the bad example? It results in bloated PDFs because the static content of the form is added redundantly as many times as you copy the form. PdfSmartCopy checks for redundant information and will add the static content only once.
P.S. 2: Why is there a bad way of doing it? The bad way of doing it, is actually a good way if the documents you are merging are all very different. In this case, the bad way is much faster and less memory-extensive and therefore actually the good way. It's only bad when you're merging documents that are very similar to each other, such as the same form filled out with different data sets.

Existing PDF to PDF/A "conversion"

I am trying to make an existing pdf into pdf/a-1b. I understand that itext cannot convert a pdf to pdf/a in the sense making it pdf/a compliant. But it definitely can flag the document as pdf/a. However, I looked at various examples and I cannot seem to figure out how to do it. The major problem is that
writer.PDFXConformance = PdfWriter.PDFA1B;
does not work anymore. First PDFA1B is not recognized, second, pdfwriter seems to have been rewritten and there is not much information about that.
It seems the only (in itext java version) way is:
PdfAWriter writer = PdfAWriter.getInstance(document, new FileOutputStream(filename), PdfAConformanceLevel.PDF_A_1B);
But that requires a document type, ie. it can be used when creating a pdf from scratch.
Can someone give an example of pdf to pdf/a conversion with the current version of itextsharp?
Thank you.
I can't imagine a valid reason for doing this but apparently you have one.
The conformance settings in iText are intended to be used with a PdfWriter and that object is (generally) only intended to be used with new documents. Since iText was never intended to convert documents to conformance that's just the way it was built.
To do what you want to do you could either just open the original document and update the appropriate tags in the document's dictionary or you could create a new document with the appropriate entries set and then import your old document. The below code shows the latter route, it first creates a regular non-conforming PDF and then creates a second document that says it is conforming even though it may or may not. See the code comments for more details. This targets iTextSharp 5.4.2.0.
//Folder that we're working from
var workingFolder = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
//Create a regular non-conformant PDF, nothing special below
var RegularPdf = Path.Combine(workingFolder, "File1.pdf");
using (var fs = new FileStream(RegularPdf, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (var doc = new Document()) {
using (var writer = PdfWriter.GetInstance(doc, fs)) {
doc.Open();
doc.Add(new Paragraph("Hello world!"));
doc.Close();
}
}
}
//Create our conformant document from the above file
var ConformantPdf = Path.Combine(workingFolder, "File2.pdf");
using (var fs = new FileStream(ConformantPdf, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (var doc = new Document()) {
//Use PdfSmartCopy to get every page
using (var copy = new PdfSmartCopy(doc, fs)) {
//Set our conformance levels
copy.SetPdfVersion(PdfWriter.PDF_VERSION_1_3);
copy.PDFXConformance = PdfWriter.PDFX1A2001;
//Open our new document for writing
doc.Open();
//Bring in every page from the old PDF
using (var r = new PdfReader(RegularPdf)) {
for (var i = 1; i <= r.NumberOfPages; i++) {
copy.AddPage(copy.GetImportedPage(r, i));
}
}
//Close up
doc.Close();
}
}
}
Just to be 100% clear, this WILL NOT MAKE A CONFORMANT PDF, just a document that says it conforms.