I am using This example for the latest Itext7 to fill in a document and I am getting this error: iText.Kernel.Crypto.BadPasswordException: PdfReader is not opened with owner password
So I looked around the net I found that some people found solution to this error using PdfReader.unethicalreading = true; but when I try to use this same code it says there is no definition in PDFReader named unethicalreading
Here is the Code I have:
string src = #"C:\test1.pdf";
string dest = #"C:\Test2.pdf";
PdfDocument pdfDoc = new PdfDocument(new PdfReader(src), new PdfWriter(dest));
PdfAcroForm form = PdfAcroForm.GetAcroForm(pdfDoc, true);
IDictionary<String, PdfFormField> fields = form.GetFormFields();
PdfFormField toSet;
fields.TryGetValue("Name", out toSet);
toSet.SetValue("Some text");
You need to change your code like this:
string src = #"C:\test1.pdf";
string dest = #"C:\Test2.pdf";
PdfReader reader = new PdfReader(src);
reader.setUnethicalReading(true);
PdfDocument pdfDoc = new PdfDocument(reader, new PdfWriter(dest));
PdfAcroForm form = PdfAcroForm.GetAcroForm(pdfDoc, true);
IDictionary<String, PdfFormField> fields = form.GetFormFields();
PdfFormField toSet;
fields.TryGetValue("Name", out toSet);
toSet.SetValue("Some text");
This will allow you to go against the permissions that were defined by the original author of the document. This also proves that setting such permissions has become obsolete, because since PDF became an ISO standard, there is no longer a penalty for removing those permissions.
Related
I am trying to add a signature to the 2nd page of a PDF Form. The PDF was created outside of IText, but it has fields that were populated using IText in C#/MVC. That part works fine.
The issue is getting the signature image to the 2nd page. I can get the image onto the 1st page and position it, but cannot get it to the 2nd page.
I have tried to using the var PdfDocument class' GetPage(x) method without any luck. I have also tried to use GetLastPage(). No luck.
I tried the above approach before flattening the fields and after but no luck.
PdfReader reader = new PdfReader(fileSource);
System.IO.MemoryStream m = new System.IO.MemoryStream();
PdfWriter writer = new PdfWriter(m);
PdfDocument pdf = new PdfDocument(reader, writer);
Document document = new Document(pdf);
PdfAcroForm form = PdfAcroForm.GetAcroForm(pdf, true);
String imageFile = "C:/Temp/signature.png";
ImageData data = ImageDataFactory.Create(imageFile);
Image img = new Image(data);
img.SetFixedPosition(50, 50);
pdf.GetPage(2);
document.Add(img);
form.FlattenFields();
document.Close();
pdf.Close();
pdfBytes = m.ToArray();
return new FileContentResult(pdfBytes, "application/pdf");
Any help would be appreciated.
I have a sample pdf, that I am filling out programmatically as such (using iText7):-
string name = TextBox1.Text.ToString();
string pdfTemplate = #"..\WebApplication1\Sample.pdf";
string newFile = #"..\WebApplication1\completed_sample.pdf";
PdfDocument pdf = new PdfDocument(new PdfReader(pdfTemplate).SetUnethicalReading(true), new PdfWriter(newFile));
PdfAcroForm form = PdfAcroForm.GetAcroForm(pdf, true);
IDictionary<String, PdfFormField> fields = form.GetFormFields();
PdfFormField toSet;
// This doesn't work //
fields.TryGetValue("TypeofApplication.1", out toSet);
toSet.SetValue("/On");
// This works //
fields.TryGetValue("FullName", out toSet);
toSet.SetValue(name);
form.FlattenFields();
pdf.Close();
I am able to fill out the text boxes in the pdf, but not to fill out the radio buttons/checkboxes.
Type of Application has two options in my cshtml page:
#Html.RadioButton("Application_Type", "New") New
#Html.RadioButton("Application_Type", "Renew") Renewal
and when I look through my values dictionary, I see that there are 3 options:
TypeofApplication
TypeofApplication.1
TypeofApplication.2
How do I set the checkboxes as checked = true.
My logic is as follow:
if(dr.Application_Type == "New"){
fields.TryGetValue("TypeofApplication.1", out toSet);
toSet.SetValue("/On");}
But this obviously doesn't work.
So the way I figured this out:-
1) I opened the pdf, set the checkbox as checked and saved it in my workspace folder.
2) Then, I programmatically opened the file and inspected the field value as such:-
string pdfTemplate = #"..\WebApplication1\Sample.pdf";
PdfDocument pdf = new PdfDocument(new PdfReader(pdfTemplate).SetUnethicalReading(true), new PdfWriter(newFile));
PdfAcroForm form = PdfAcroForm.GetAcroForm(pdf, true);
IDictionary<String, PdfFormField> fields = form.GetFormFields();
PdfFormField toSet;
fields.TryGetValue("TypeofApplication", out toSet);
var x = toSet.GetValueAsString();
Now, I know the value of x, which is the checked field. (New or Renew). I used this technique to find all values possible for any given checkbox, radiobutton list, et cetera.
I am creating an application that has to generate thousands of PDF files at a time. I am using ITextSharp to do this and it seems that the PdfReader is slowing down the process. Below is my code.
using (MemoryStream foutput = new MemoryStream())
{
using (PdfReader pdf = new PdfReader(templateByteArray)) // slow
{
using (PdfStamper stamper = new PdfStamper(pdf, foutput))
{
AcroFields form = stamper.AcroFields;
form.SetField(_dic[#"1,1"], "some string1");
form.SetField(_dic[#"1,2"], "some string2");
stamper.FormFlattening = true;
}
pdf.RemoveUsageRights();
}
EnqueueFile(foutput.ToArray());
}
I have a separate consumer thread that takes every byte array and writes the PDF documents to the HDD from a queue. After I messed around with the code, it seems that the bottleneck is in the PdfReader class. Is there an alternate way to doing what I am trying to do or do you have any suggestions?
You are reading the properties of the fields _dic[#"1,1"] and _dic[#"1,1"] over and over again. You should cache those properties. In Java, that's done like this:
HashMap<String,TextField> fieldCache = new HashMap<String,TextField>();
This cache stores information about each TextField that is encountered. You introduce it with the setFieldCache() method:
public void manipulatePdf(String src, String dest,
HashMap<String,TextField> cache, String name, String login)
throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
AcroFields form = stamper.getAcroFields();
form.setFieldCache(cache);
form.setField("test", "test");
stamper.close();
reader.close();
}
The first time the field with name "test" is encountered, the information will be read from the existing file. The next time it is encountered, the TextField info will be retrieved from the cache instead of from the existing file.
I'm trying to add new page to a PdfStamper but this code doesn't add the template pdf fields to the stamper.
private void InsertNewPage(PdfStamper stamper, int pageNumber)
{
var pdfReader = new PdfReader(UrlTemplateBlankPage);
pdfReader.SelectPages("1");
stamper.InsertPage(pageNumber, pdfReader.GetPageSize(1));
stamper.GetOverContent(pageNumber).AddTemplate(stamper.GetImportedPage(pdfReader, 1), 0, 0);
//This code doesn't work because the code before is not adding the form
var pdfFormFields = stamper.AcroFields;
var fieldKeys = pdfReader.AcroFields.Fields.Keys;
foreach (var k in fieldKeys.ToList())
{
pdfFormFields.RenameField(k, k + string.Format("_{0:000}", pageNumber));
}
}
I searched online but I can't find an answer about my problem.
The PDF template I'm adding has some fields added with Acrobat. I can't attach the template but I can give you all informations.
I cannot see how do you instantiate the stamper. This is an example about how to read a PDF template and assign it to the stamper:
var reader = new PdfReader(TEMPLATE_PATH);
var pdfOutput = new FileStream(PDF_OUTPUT_PATH, FileMode.Create)
var stamper = new PdfStamper(reader, pdfOutput);
After that, you can set the fields using the SetField function:
stamper.AcroFields.SetField("FIELD1", "VALUE")
There is an option to make your fillable PDFs non-editable using:
stamper.FormFlattening = true;
Otherwise, your PDF still fillable.
Once you have finished working with your files, close them:
stamper.Close();
reader.Close();
There is an example about how to use iTextSharp's PdfStamper in the next link: http://www.codeproject.com/Tips/679606/Filling-PDF-Form-using-iText-PDF-Library
I am trying to find out if it is possible to read PDF Form data (Forms filled in and saved with the form) using iTextSharp. How can I do this?
You would have to find out the field names in the PDF form. Get the fields and then read their value.
string pdfTemplate = "my.pdf";
PdfReader pdfReader = new PdfReader(pdfTemplate);
AcroFields fields = pdfReader.AcroFields.Fields;
string val = fields.GetField("fieldname");
Obviously in the code above, field name is the name of the PDF form field and the GetField method returns a string representation of that value.
Here is an article with example code that you could probably use. It shows how you can both read and write form fields using iTextSharp.
Maybe the iTextSharp library has changed recently but I wasn't able to get the accepted answer to work. Here is my solution:
var pdf_filename = "pdf2read.pdf";
using (var reader = new PdfReader(pdf_filename))
{
var fields = reader.AcroFields.Fields;
foreach (var key in fields.Keys)
{
var value = reader.AcroFields.GetField(key);
Console.WriteLine(key + " : " + value);
}
}
A very subtle difference, due to reader.AcroFields.Fields returning an IDictionary instead of just an AcroFields object.
If you are using Powershell, the discovery code for fields is:
Add-Type -Path C:\Users\Micah\Desktop\PDF_Test\itextsharp.dll
$MyPDF = "C:\Users\Micah\Desktop\PDF_Test\something_important.pdf"
$PDFDoc = New-Object iTextSharp.text.pdf.pdfreader -ArgumentList $MyPDF
$PDFDoc.AcroFields.Fields
That code will give you the names of all the fields on the PDF Document, "something_important.pdf".
This is how you access each field once you know the name of the field:
$PDFDoc.AcroFields.GetField("Name of the field here")
This worked for me!
Note the parameters when defining stamper! '\0', true
string TempFilename = Path.GetTempFileName();
PdfReader pdfReader = new PdfReader(FileName);
//PdfStamper stamper = new PdfStamper(pdfReader, new FileStream(TempFilename, FileMode.Create));
PdfStamper stamper = new PdfStamper(pdfReader, new FileStream(TempFilename, FileMode.Create), '\0', true);
AcroFields fields = stamper.AcroFields;
AcroFields pdfFormFields = pdfReader.AcroFields;
foreach (KeyValuePair<string, AcroFields.Item> kvp in fields.Fields)
{
string FieldValue = GetXMLNode(XMLFile, kvp.Key);
if (FieldValue != "")
{
fields.SetField(kvp.Key, FieldValue);
}
}
stamper.FormFlattening = false;
stamper.Close();
pdfReader.Close()
The PDF name is "report.pdf"..
The data field to be read into TextBox1 is "TextField25" in the PDF..
Dim pdf As String = "report.pdf"
Dim reader As New PdfReader(pdf)
Dim fields As AcroFields = reader.AcroFields
TextBox1.Text = fields.GetField("TextField25")
Important Note: This can be used ONLY IF the PDF is not flattened (means the fields should be editable) while it was created using iTextSharp..
i.e.
pdfStamper.FormFlattening = False
This is very simple.. And it works like a charm.. :)
If anybody is still wondering about this answer, this is how I extracted the text in the field (provided you know the field name):
PdfReader reader = new("filepath");
PdfDocument doc = new(reader);
PdfAcroForm form = PdfAcroForm.GetAcroForm(document, false);
Form.GetField("FieldNameHere").GetValueAsString();
Works for iText 7.1.16