pdfbox - unable to capture modified values from pdf - pdfbox

I have a requirement to open PDF on JXBrowser and let the user modify values on PDF and upon saving, I should able to read the modified values and save to database.
My issue was, I am unable to fetch modified values from pdf, its always sending back original values from pdf (acroForm.getField(field name);). Could you help me if there is any other way to solve this problem.
I am using pdfbox 2.0.1
Appreciate your help.
Thanks,
Prasad
Update1:
Adding sample code that I have used in my application
PDDocument PDFDoc = PDDocument.load(complaintform.pdf);
LoggerProvider.setLevel(Level.OFF);
Base64Encoder b64 = new Base64Encoder();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PDFDoc.save(baos);
String pdfHTML = "<HTML><BODY style=\"width:100%; height:100%\" > <embed style=\"width:100%; height:100%\" src=\"data:application/pdf;base64,"+b64.encode(baos.toByteArray())+"\"type=\"application/pdf\"></BODY></HTML>";
Browser browser = new Browser();
BrowserView browserView = new BrowserView(browser);
this.add(browserView, BorderLayout.CENTER);
browser.loadHTML(pdfHTML);
save()
{
PDDocumentCatalog docCatalog = PDFDoc.getDocumentCatalog();
PDAcroForm acroForm = docCatalog.getAcroForm();
PDField field = acroForm.getField("last");
String modifiedValue = field.getValueAsString();
}

Related

How to create PDF/UA in iText7 with text hyperlink

I am trying to create a PDF/UA compliant file that contains a text hyperlink with iText 7. Both the Acrobat Preflight test for PDF/UA and the PDF Accessibility Checker (PAC 3) complain that the PDF file say that the PDF is not compliant.
PAC 3 says ""Link" annotation is not nested inside a "Link" structure element" and the Acrobat Preflight test says the Link annotation does not have an alternate description in the Contents key.
The following is my attempt to create PDF/UA compliant output that contains a text hyperlink.
Any advice would be appreciated.
public void testHyperLink() throws IOException {
// Create PDF/UA with text hyperlink
String filename = "./results/HyperLink.pdf";
WriterProperties properties = new WriterProperties();
properties.addUAXmpMetadata().setPdfVersion(PdfVersion.PDF_1_7);
PdfWriter writer = new PdfWriter(filename, properties);
pdfDoc = new PdfDocument(writer);
//Make document tagged
pdfDoc.setTagged();
pdfDoc.getCatalog().setLang(new PdfString("en-US"));
pdfDoc.getCatalog().setViewerPreferences(new PdfViewerPreferences().setDisplayDocTitle(true));
PdfDocumentInfo info = pdfDoc.getDocumentInfo();
info.setTitle("Hello Hyperlinks!");
document = new Document(pdfDoc);
// Must embed font for PDF/UA
byte[] inputBytes = Files.readAllBytes(Paths.get("./resources/fonts/opensans-regular.ttf"));
boolean embedded = true;
boolean cached = false;
PdfFont font = PdfFontFactory.createFont(inputBytes, PdfEncodings.CP1252, embedded, cached);
Text text = new Text("This is a Text link");
text.setFont(font);
text.setFontSize(16F);
// Add alternate text for hyperlink
text.getAccessibilityProperties().setAlternateDescription("Click here to go to the iText website");
PdfAction act = PdfAction.createURI("https://itextpdf.com/");
text.setAction(act);
Paragraph para = new Paragraph();
para.add(text);
document.add(para);
document.close();
System.out.println("Created "+ filename);
}
A Link object might be what you want:
Link lnk = new Link("This is a Text link",
PdfAction.CreateURI("https://itextpdf.com/"));
lnk.SetFont(font);
lnk.GetLinkAnnotation().SetBorder(new PdfAnnotationBorder(0, 0, 0));//Remove the default border
lnk.GetAccessibilityProperties().SetAlternateDescription("Click here to go to the iText website");
Paragraph para = new Paragraph();
para.Add(lnk);
document.Add(para);

Generate PDF from gsp page

I am using grails 2.5.2.
I have created a table which shows all the data from database to gsp page and now i need to save that shown data in a pdf format with a button click.What will be the best way to show them into a PDF and save it to my directory. please Help
You can use itext for converting HTML into pdf using the code below:
public void createPdf(HttpServletResponse response, String args, String css, String pdfTitle) {
response.setContentType("application/force-download")
response.setHeader("Content-Disposition", "attachment;filename=${pdfTitle}.pdf")
Document document = new Document()
Rectangle one = new Rectangle(900, 600)
document.setPageSize(one)
PdfWriter writer = PdfWriter.getInstance(document, response.getOutputStream())
document.open()
ByteArrayInputStream bis = new ByteArrayInputStream(args.toString().getBytes())
ByteArrayInputStream cis = new ByteArrayInputStream(css.toString().getBytes())
XMLWorkerHelper.getInstance().parseXHtml(writer, document, bis, cis)
document.close()
}
Though answering this question late,take a look at grails export plugin.It will be useful if you want to export your data to excel and pdf( useful only if there is no in pre-defined template to export).
Got idea from itext. Used itext 2.1.7 and posted all the values to pdf from a controller method. Used images as background and paragraph and phrase to show values from database.

PDF generated using PDFBox is magnified when printing / saving via Safari

I generated a pdf using PDFBox which is then sent to the front-end. When I print / save this pdf in Chrome / Firefox, it looks good. However, when I try to do the same using Safari, the pdf is magnified.
Not sure if this is a browser issue or whether it has something to do with Safari not able to read the pdf properly. Any ideas?
This is the pdf generated from Chrome, and this is the one from Safari (I've redacted few details).
This is my code:
PDXObjectImage blankImg = (PDXObjectImage) object;
if(blankImg.getHeight() > 460){
BufferedImage img = ImageIO.read(new ByteArrayInputStream(shippingLabel));
BufferedImage resizedImage = Scalr.resize(img, Scalr.Method.BALANCED, Scalr.Mode.FIT_EXACT, img.getWidth(), img.getHeight());
// Convert images to jpg format
BufferedImage jpegImage = new BufferedImage(resizedImage.getWidth(),resizedImage.getHeight(), BufferedImage.TYPE_INT_RGB);
jpegImage.createGraphics().drawImage(resizedImage, 0, 0, Color.WHITE, null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(jpegImage, "jpg", baos);
// Replace empty image in template with the image generated from shipping label byte array
PDXObjectImage carrierLabel = new PDJpeg(doc, new ByteArrayInputStream(baos.toByteArray()));
blankImg.getCOSStream().replaceWithStream(carrierLabel.getCOSStream());
break;
}
PDStream updatedStream = new PDStream(doc);
OutputStream out = updatedStream.createOutputStream();
ContentStreamWriter tokenWriter = new ContentStreamWriter(out);
tokenWriter.writeTokens(tokens);
page.setContents(updatedStream);
// Convert PDDoc to byte[]
ByteArrayOutputStream outUpdated = new ByteArrayOutputStream();
doc.save(outUpdated);
return outUpdated.toByteArray();
This is what I'm doing. I have a pdf with a blank image. I read this image, and replace this with another existing image which is available as byte array, and finally return the updated pdf as a byte array as ResponseEntity from Spring boot server running in the backend.
Thanks.

itextsharp stamper vs smartcopy, show pdf in browser without toolbar or navpanes

My application is grabbing pdf bytes from our db and sending the pdf to an iframe, using the itextsharp library. When the pdf is displayed in the iframe, the toolbar and navigation pane show, but we'd like to hide those. When I load a pdf document by simply typing in the pdf's url with #toolbar=0&navpanes=0, I see the result I'm looking for.
The application logic is using PdfStamper to add some buttons and other data to the pdf. When I write the pdf to the Response.Outputstream, the pdf shows up with the added buttons, and all is good except that I can't get rid of the toolbar and navpanes. I've tried adding "toolbar=0&navpanes=0" to the url in the response header, but to no avail.
I've written a test application which shows that using PdfSmartCopy instead of the stamper works perfectly - the pdf is shown in the browser which hides the toolbar and navpane by default.
The problem is that I still need to add some buttons to the pdf via the stamper. I've written a test app which adds the buttons via the stamper, then the smart copy grabs each page from the stamper and writes all this out to the Response.Output. The pdf shows in the browser with no toolbar or navpanes, but the buttons are not there.
Here is the code which uses both the stamper and the smart copy - your help is greatly appreciated:
private void SendStamperToCopy()
{
try
{
String filePath = #"C:\debug\PerfIndicWithDefaults.pdf";
byte[] pdfBytes = ReadFile(filePath);
Document document = new Document();
PdfSmartCopy copy = new PdfSmartCopy(document, Response.OutputStream);
document.Open();
MemoryStream memStream = new MemoryStream();
PdfReader reader = new PdfReader(pdfBytes);
PdfStamper pdfStamper = new PdfStamper(reader, memStream);
// add a button with the stamper
iTextSharp.text.Rectangle rectCancel = new iTextSharp.text.Rectangle(50, 50, 20, 20);
PushbuttonField btnCancel = new PushbuttonField(pdfStamper.Writer, rectCancel, "Cancel");
btnCancel.Text = "Cancel";
iTextSharp.text.pdf.PdfAnnotation fieldCancel = btnCancel.Field;
pdfStamper.AddAnnotation(fieldCancel, 1);
int numOfPgs = reader.NumberOfPages;
for (int n = 1; n <= numOfPgs; n++)
{
copy.AddPage(pdfStamper.GetImportedPage(reader, n));
}
String headerStr = "inline; filename=PerfIndicWithDefaults.pdf";
Response.AppendHeader("content-disposition", headerStr);
Response.ContentType = "application/pdf";
Response.OutputStream.Flush();
document.Close();
Response.OutputStream.Close();
}
catch (Exception ex)
{
Console.Write(ex);
Response.OutputStream.Flush();
Response.OutputStream.Close();
}
}
If I understand your question correctly, you want to use PdfStamper to add a button and you want to change the viewer preferences. This can be done like this:
PdfReader reader = new PdfReader(source);
System.IO.MemoryStream m = new System.IO.MemoryStream();
PdfStamper stamper = new PdfStamper(reader, m);
PdfStamper.ViewerPreferences = PdfWriter.HideToolbar | PdfWriter.PageModeUseNone;
stamper.Close();
reader.Close();
The HideToolbar will hide the toolbar, whereas PageModeUseNone means that you don't show any panels (such as the bookmarks panel, etc...).
It is not clear why you would need PdfSmartCopy in this context. Maybe I'm missing something. Also: there are some strange errors in your code: you never close the stamper instance, yet you import a page from the stamper into the copy instance. I've never seen any one try that. It's certainly not what I had in mind when I wrote iText. Your code is very confusing to me.

Losing javascript which is added into pdf using itext

I am trying to add javascript into a pdf using itext and later merge it with another pdf.
But the final merged pdf does not contain the javascript. The javascript is working fine if the pdf is not merged with another pdf.
Merging code :
FileOutputStream sectionR = new FileOutputStream(RESULT);
PdfCopyFields copier = new PdfCopyFields(sectionR);
for (String curInPath : listFile) {
PdfReader reader = new PdfReader(curInPath);
copier.addDocument(reader);
}
copier.close();
I tried to add JS to the resulting merged pdf, but it is not taking it. I guess its not editable.
Below is the code adding JS to pdf which is not merged yet.
FileOutputStream section1Pdf = new FileOutputStream("newPDFSection");
PdfReader readerSection1 = new PdfReader("Existing PDF - Section 1");
PdfStamper stamperSection1 = new PdfStamper(readerSection1,section1Pdf);
stamperSection1.addJavaScript(
"var nameField = this.getField('txtOwnerCity');" + "nameField.setAction('Keystroke'," +"'forceUpperCase()');" +
"" +"function forceUpperCase(){" +
"if(!event.willCommit)event.change = " +
"event.change.toUpperCase();" +
"}");
When I tried adding JS to the resulting merged pdf, it does not allow me saying it is not editable anymore.
This is how I am trying to add
FileOutputStream sectionR = new FileOutputStream(RESULT);
PdfCopyFields copier = new PdfCopyFields(sectionR);
for (String curInPath : listFile) {
PdfReader reader = new PdfReader(curInPath);
copier.addDocument(reader);
}
copier.close();
PdfReader readersectionResult = new PdfReader("result.pdf");
PdfStamper stamper = new PdfStamper(readersectionResult, new FileOutputStream("newResult.pdf"));
stamper.addJavaScript(some JS);
The error I am getting is ' WARNING: Cannot set header. Response already committed.'
I am not sure if I am doing it right above, All I am trying to do is get pdfstamper of resulting pdf to add new JS to it.
When I am trying to edit form filed values, it says not editable anymore.
AcroFields acro= stamper .getAcroFields();
acro.setField("txtOfficerName"+officerChar,officerSO.getFullName());