Aspose pdf java PdfFileSignature setAuthority not working - java

I'm trying to use Aspose pdf java to digitally sign a document. This is my code
public ByteArrayOutputStream signDocument(Document doc, String signedBy) throws Exception {
PdfFileSignature pdfSignSingle = new PdfFileSignature();
pdfSignSingle.bindPdf(doc);
pdfSignSingle.setCertificate(prop.getSigningKeyStorePath(), prop.getKeystorePassword());
PKCS7 signature = new PKCS7(prop.getSigningKeyStorePath(), prop.getKeystorePassword());
pdfSignSingle.setSignatureAppearance(prop.getSimploudLogo());
signature.setAuthority("Authority");
signature.setDate(new Date());
signature.setContactInfo("email");
signature.setLocation("Location");
signature.setReason("reason");
pdfSignSingle.sign(1, true, new java.awt.Rectangle(100, 100, 200, 200), signature);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
pdfSignSingle.save(baos);
pdfSignSingle.dispose();
doc.dispose();
return baos;
}
In picture is shown how the signature looks in adobeReader.
As you can see both image and Authority are not shown. I tried image to be both in pdf and png format. I've also tried to make it smaller then Rectangle area. As for authority i really need it to be customizable so that text in first line in picture can be
Signed by "customParameter"

The API offers another Class i.e. SignatureCustomAppearance which can further be used to set such properties for a signature such as DateSigned, Reason, Location, etc. Please check the following complete code snippet which can fulfill your requirements:
String inputFile = "doc.pdf";
String outSignedFile = "out_20.9.pdf";
// Create PdfFileSignature instance
com.aspose.pdf.facades.PdfFileSignature pdfSignSingle = new com.aspose.pdf.facades.PdfFileSignature();
// Bind the source PDF by reading contents of Stream
pdfSignSingle.bindPdf(inputFile);
PKCS7 pkcs = new PKCS7("mykey2.pfx", "pass");
pkcs.setAuthority("Authority");
pkcs.setDate(new Date());
pkcs.setContactInfo("email");
pkcs.setLocation("Location");
pkcs.setReason("reason");
pkcs.setImage(new FileInputStream("simpleLogo.png"));
SignatureCustomAppearance sca = new SignatureCustomAppearance();
sca.setDateSignedAtLabel(null);
sca.setDigitalSignedLabel(null);
sca.setShowReason(true);
sca.setShowLocation(true);
sca.setShowContactInfo(true);
pkcs.setCustomAppearance(sca);
pdfSignSingle.sign(1, true, new java.awt.Rectangle(100, 100, 200, 200), pkcs);
// Set image for signature appearance
//pdfSignSingle.setSignatureAppearance("simpleLogo.png");
// Save final output
pdfSignSingle.save(outSignedFile);
As mentioned in the comment below the question, the same inquiry was posted in Aspose.PDF official forum as well at "Aspose pdf java PdfFileSignature setAuthority not working" and a solution has also been provided there.

Related

How do you add multiple images to a PDF with itext7 Java?

First google result takes me to Add multiple images into a single pdf file with iText using java which was posted 5 years ago. I am not sure which version they are using, because the Image object doesn't even have the getInstance method for me. Needless to say I am not getting much help from that link.
Anyways I am trying to create a javaFX application that loops multiple JPG images to create a single PDF document. Below is my code, which successfully creates a PDF from 2 images, but I am having trouble making the second image display on the second page.
In the link I posted above the simple solution I saw was to do document.newPage() then do document.add(img), but my document object doesn't have that method? I am not sure what to do.
PdfWriter writer = new PdfWriter("D:/sample1.pdf");
// Creating a PdfDocument
PdfDocument pdfDoc = new PdfDocument(writer);
// Adding a new page
// I can add multiple pages here, but when I add multiple images they do not
// automatically flow over to the next page.
pdfDoc.addNewPage();
pdfDoc.addNewPage();
// Creating a Document
Document document = new Document(pdfDoc);
String imageFile = "C:/Users/***/Downloads/MAT204/1.3-1.4 HW/test.jpg";
ImageData data = ImageDataFactory.create(imageFile);
Image img = new Image(data);
img.setAutoScale(true);
img.setRotationAngle(-Math.toRadians(90));
// I can add multiple images, but they overlaps each other and only
// appears on the first page.
// Is there a way for me to change the current page to write on?
document.add(img);
document.add(img);
// Closing the document
document.close();
System.out.println("PDF Created");
Anyways, I just want to figure out how to manually add another image before I write a loop to automate the process.
After doing more research I found the answer here.
https://kb.itextpdf.com/home/it7kb/examples/multiple-images
protected void manipulatePdf(String dest) throws Exception {
Image image = new Image(ImageDataFactory.create(IMAGES[0]));
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
Document doc = new Document(pdfDoc, new PageSize(image.getImageWidth(), image.getImageHeight()));
for (int i = 0; i < IMAGES.length; i++) {
image = new Image(ImageDataFactory.create(IMAGES[i]));
pdfDoc.addNewPage(new PageSize(image.getImageWidth(), image.getImageHeight()));
image.setFixedPosition(i + 1, 0, 0);
doc.add(image);
}
doc.close();
}

While parsing pdf with iText7 chars move on fixed interval (with Freeset font)

I'm trying to parse pdf that I have created with iText. In document I have two paragraphs:
"Имя" - ("name" from Russian) - font: Helvetica, size: 20.
"Фамилия" - ("surname" from Russian) - font: Freeset (I downloaded it here), size: 10.
When I finish parsing I get "Имя" properly encoded and "Ôàìèëèÿ" instead of "Фамилия". It is Unicode characters for "Фамилия" but moved 848 chars (10-based) left. (I mean that, for instance, instead of "Ф" (0x0424 in UTF-8) I get "Ô" (0x00d4) and difference between them is 848 (or 350 in hex))
I use this example to get text from pdf (but instead of filtering by font, I filter by equality to one of the Strings in the set ("Имя", "Фамилия")
I know that we are advised to store non-English charactes as sequence of Unicode symbols, but I'm creating pdf on the fly from incoming data so I can't manually retype it as separate Unicode symbols (if you know how to do it on the fly, please provide your approach).
Any ideas why this movement of character happen and how to avoid it are welcomed. Thank you in advance.
Here is the file I worked with.
Edit
I tried opening file in Acrobat Pro and everything is fine there. Acrobat also shows that all three fonts I've put in pdf are still in the document.
Here is the code I used to create pdf I'm processing:
private static void create() throws IOException {
PdfDocument pdf = new PdfDocument(new PdfReader(srcPdf), new PdfWriter(targetPdf));
PdfCanvas pdfCanvas = new PdfCanvas(pdf.getFirstPage());
PdfFont freeset = getPdfFont(freesetPath);
PdfFont helvetica = getPdfFont(helveticaPath);
PdfFont circe = getPdfFont(circePath);
pdfCanvas.beginText()
.setFontAndSize(helvetica, 15)
.setColor(Color.RED, true)
.moveText(50, 300)
.showText("Имя")
.setFontAndSize(freeset, 10)
.setColor(Color.GREEN, true)
.moveText(0, -30)
.showText("Фамилия")
.setFontAndSize(circe, 20)
.setColor(Color.BLUE, true)
.moveText(0, -30)
.showText("Должность")
.endText();
pdf.close();
}
private static PdfFont getPdfFont(String path) throws IOException {
InputStream fontInputStream = new FileInputStream(path);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[2048];
int a;
while((a = fontInputStream.read(buffer, 0, buffer.length)) != -1) {
baos.write(buffer, 0, a);
}
baos.flush();
return PdfFontFactory.createFont(baos.toByteArray(),
PdfEncodings.IDENTITY_H, true);
}
iText 7 appears to have an issue with embedding the font in question. I don't know whether it's a bug in the font or in iText, though.
The "FreeSet" font is indeed embedded in the OP's sample document with a wrong ToUnicode map
...
6 beginbfrange
<009e> <009e> <00d4> <00aa> <00aa> <00e0> <00b2> <00b2> <00e8> <00b5> <00b5> <00eb> <00b6> <00b6> <00ec> <00c9> <00c9> <00ff> endbfrange
...
which maps the glyphs used for "Фамилия" to 00d4, 00e0, 00e8, 00eb, 00ec, and 00ff.
This in turn explains why both iText and Adobe Reader extract unexpected text.
The issue can be reproduced like this:
PdfFont arial = PdfFontFactory.createFont(BYTES_OF_ARIAL_FONT, PdfEncodings.IDENTITY_H, true);
PdfFont freeSet = PdfFontFactory.createFont(BYTES_OF_FREESET_FONT, PdfEncodings.IDENTITY_H, true);
try ( OutputStream result = new FileOutputStream("cyrillicTextFreeSet.pdf");
PdfWriter writer = new PdfWriter(result);
PdfDocument pdfDocument = new PdfDocument(writer);
Document doc = new Document(pdfDocument) ) {
doc.add(new Paragraph("Фамилия").setFont(arial));
doc.add(new Paragraph("Фамилия").setFont(freeSet));
}
(CreateCyrillicText test testCreateTextWithFreeSet)
The result looks ok:
When extracting / copying&pasting, though:
The embedded Arial subset has a proper ToUnicode map, the text in Arial is extracted as "Фамилия".
The embedded FreeSet subset has an incorrect ToUnicode map, the text in FreeSet is extracted as "Ôàìèëèÿ".
(Tested with the current iText 7.1.1-SNAPSHOT)
Apparently iText 7 does understand the FreeSet font program well enough to select the needed subset and reference the correct glyphs from the content but it has problems building an appropriate ToUnicode map. This is not a general problem, though, as the parallel test with Arial shows.

Using fonts in custom signatureAppearance signatures with iText7 breaks PDF/A conformance?

I am trying to create signed PDFs from PDF/A-1A input files, the output must preserve the conformance level.
The signatures have to be added with a customized appearance.
If I do it along the code lines below, everything works on the signature side, and the signature is diplayed correctly and verifies OK.
But the PDF/A conformance is broken by the embedded fonts that do not contain the required toUnicode CMAPs.
PdfADocument pdf = ... the doc to be signed
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
PdfReader reader = pdf.getReader();
PrivateKey privateKey = ...
Provider signatureProvider = new BouncyCastleProvider();
Certificate[] signChain = ...
PdfSigner pdfSigner = new PdfSigner(reader, buffer, true);
PdfSignatureAppearance signatureAppearance = pdfSigner.getSignatureAppearance();
signatureAppearance.setReuseAppearance(false);
signatureAppearance.setPageNumber(pdf.getNumberOfPages());
pdfSigner.setFieldName("Custom Signature");
float margin = 35;
Rectangle pageSize = pdf.getLastPage().getMediaBox();
Rectangle signaturePosition = new Rectangle(pageSize.getLeft()+margin,
pageSize.getBottom()+margin,
pageSize.getWidth()-2*margin,
(pageSize.getHeight()-2*margin)/3);
// need to do this before creating any *Canvas object, else the pageRect will be null and the signature invisible
signatureAppearance.setPageRect(signaturePosition);
PdfFont regularFont = PdfFontFactory.createFont("/path/to/truetypefile-regular.ttf", "ISO-8859-1", true);
PdfFont boldFont = PdfFontFactory.createFont("/path/to/truetypefile-bold.ttf", "ISO-8859-1", true);
int fontSize = 10;
PdfFormXObject n0 = signatureAppearance.getLayer0();
PdfCanvas n0Canvas = new PdfCanvas(n0, pdfSigner.getDocument());
PdfFormXObject n2 = signatureAppearance.getLayer2();
Canvas n2Canvas = new Canvas(n2, pdfSigner.getDocument());
if(regularFont != null) {
n2Canvas.setFont(regularFont);
n0Canvas.setFontAndSize(regularFont, fontSize);
}
ImageData imageData = ImageDataFactory.create("/path/to/image.png");
Image image = new Image(imageData);
n2Canvas.add(image);
String layer2Text = ... some lines of text containing newlines and some simple markdown
String[] paragraphs = layer2text.split("\n\n");
for (String text : paragraphs) {
boolean bold = false;
if(text.startsWith("[bold]")) {
bold = true;
text = text.replaceFirst("^\\s*\\[bold\\]\\s*", "");
}
Paragraph p = new Paragraph(text);
p.setFontSize(fontSize);
if(bold) {
p.setFont(boldFont);
}
n2Canvas.add(p);
}
... pdfSigner.setCertificationLevel(PdfSigner.CERTIFIED_FORM_FILLING_AND_ANNOTATIONS);
PrivateKeySignature externalSignature = new PrivateKeySignature(privateKey, DigestAlgorithms.SHA512, signatureProvider.getName());
BouncyCastleDigest externalDigest = new BouncyCastleDigest();
pdfSigner.signDetached(externalDigest, externalSignature, signChain, null, null, null, 0, PdfSigner.CryptoStandard.CMS);
So I assume there is something missing there. The fonts that get embedded to not conform to PDF/A because they miss the ToUnicode CMAP key.
Another error from pdf-tools validator says:
"The value of the key Encoding is Difference but must be WinAnsiEncoding or MacRomanEncoding." Which seems to be the same problem.
The signature itself is OK and visibly, styling and image in place as should be. It's just the fonts that seem to not be OK.
The trigger for the violation of the PDF/A compliance is the way the fonts are created here
PdfFont regularFont = PdfFontFactory.createFont("/path/to/truetypefile-regular.ttf", "ISO-8859-1", true);
PdfFont boldFont = PdfFontFactory.createFont("/path/to/truetypefile-bold.ttf", "ISO-8859-1", true);
or even more specifically the encoding parameter "ISO-8859-1" used therein.
The PDF/A-1 specification requires:
6.3.7 Character encodings
All non-symbolic TrueType fonts shall specify MacRomanEncoding or WinAnsiEncoding as the value of the
Encoding entry in the font dictionary. All symbolic TrueType fonts shall not specify an Encoding entry in the
font dictionary, and their font programs' “cmap” tables shall contain exactly one encoding.
The use of the encoding parameter "ISO-8859-1" caused a neither MacRomanEncoding nor WinAnsiEncoding to be specified as the value of the
Encoding entry in the font dictionary. Instead the value is a dictionary containing only a Differences entry containing an explicit mapping.
Depending on the PDF/A validator this may result in different error messages.
For (as I assume) historic reasons there are a few different encoding parameter values during font creation which cause iText to use WinAnsiEncoding:
""
PdfEncodings.WINANSI (== "Cp1252")
"winansi" (case-insensitive)
"winansiencoding" (case-insensitive)
The OP used PdfName.WinAnsiEncoding.getValue() which returns a string matching the latest option.
While this indicates that iText can be used to properly sign PDF/A documents, a specific PDFASigner class enforcing conformance probably should be introduced.

Attachment damages signature part 2

I created code that adds an image to an existing pdf document and then signs it, all using PDFBox (see code below).
The code nicely adds the image and the signature. However, in some documents, Acrobat Reader complains that "The signature byte range is invalid."
The problem seems to be the same as the problem described in this question. The answer to that question describes the problem in more detail: the problem is that my code leaves a mix of cross reference types in the document (streams and tables). Indeed, some documents won't even open because of the problems that this creates.
My question is: how do I prevent this? How do I add an image to an existing pdf document without creating multiple cross reference types?
public class TC3 implements SignatureInterface{
private char[] pin = "123456".toCharArray();
private BouncyCastleProvider provider = new BouncyCastleProvider();
private PrivateKey privKey;
private Certificate[] cert;
public TC3() throws Exception{
Security.addProvider(provider);
KeyStore keystore = KeyStore.getInstance("PKCS12", provider);
keystore.load(new FileInputStream(new File("resources/IIS_keystore.pfx")), pin.clone());
String alias = keystore.aliases().nextElement();
privKey = (PrivateKey) keystore.getKey(alias, pin);
cert = keystore.getCertificateChain(alias);
}
public void doSign() throws Exception{
byte inputBytes[] = IOUtils.toByteArray(new FileInputStream("resources/rooster.pdf"));
PDDocument pdDocument = PDDocument.load(new ByteArrayInputStream(inputBytes));
PDJpeg ximage = new PDJpeg(pdDocument, ImageIO.read(new File("resources/logo.jpg")));
PDPage page = (PDPage)pdDocument.getDocumentCatalog().getAllPages().get(0);
PDPageContentStream contentStream = new PDPageContentStream(pdDocument, page, true, true);
contentStream.drawXObject(ximage, 50, 50, 356, 40);
contentStream.close();
ByteArrayOutputStream os = new ByteArrayOutputStream();
pdDocument.save(os);
os.flush();
pdDocument.close();
inputBytes = os.toByteArray();
pdDocument = PDDocument.load(new ByteArrayInputStream(inputBytes));
PDSignature signature = new PDSignature();
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
signature.setName("signer name");
signature.setLocation("signer location");
signature.setReason("reason for signature");
signature.setSignDate(Calendar.getInstance());
pdDocument.addSignature(signature, this);
File outputDocument = new File("resources/signed.pdf");
ByteArrayInputStream fis = new ByteArrayInputStream(inputBytes);
FileOutputStream fos = new FileOutputStream(outputDocument);
byte[] buffer = new byte[8 * 1024];
int c;
while ((c = fis.read(buffer)) != -1)
{
fos.write(buffer, 0, c);
}
fis.close();
FileInputStream is = new FileInputStream(outputDocument);
pdDocument.saveIncremental(is, fos);
pdDocument.close();
}
public byte[] sign(InputStream content) {
CMSProcessableInputStream input = new CMSProcessableInputStream(content);
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
List<Certificate> certList = Arrays.asList(cert);
CertStore certStore = null;
try{
certStore = CertStore.getInstance("Collection", new CollectionCertStoreParameters(certList), provider);
gen.addSigner(privKey, (X509Certificate) certList.get(0), CMSSignedGenerator.DIGEST_SHA256);
gen.addCertificatesAndCRLs(certStore);
CMSSignedData signedData = gen.generate(input, false, provider);
return signedData.getEncoded();
}catch (Exception e){}
return null;
}
public static void main(String[] args) throws Exception {
new TC3().doSign();
}
The issue
As had already been explained in this answer, the issue at work here is that
when non-incrementally storing the document with the added image, PDFBox 1.8.9 does so using a cross reference table no matter if the original file used a table or stream; if the original file used a stream, the cross reference stream dictionary entries are copied into the trailer dictionary;
...
0000033667 00000 n
0000033731 00000 n
trailer
<<
/DecodeParms <<
/Columns 4
/Predictor 12
>>
/Filter /FlateDecode
/ID [<5BD95916CAE5E84E9D964396022CBDCD> <6420B4547602C943AF37DD6C77496BE8>]
/Info 6 0 R
/Length 61
/Root 1 0 R
/Size 35
/Type /XRef
/W [1 2 1]
/Index [20 22]
>>
startxref
35917
%%EOF
(Most of these trailer entries here are useless or even misleading, see below.)
when incrementally saving the signature, COSWriter.doWriteXRefInc uses COSDocument.isXRefStream to determine whether the existing document (the one we stored as above) uses a cross reference stream. As mentioned above, it does not. Unfortunately, though, COSDocument.isXRefStream in PDFBox 1.8.9 is implemented as
public boolean isXRefStream()
{
if (trailer != null)
{
return COSName.XREF.equals(trailer.getItem(COSName.TYPE));
}
return false;
}
Thus, the misleading trailer entry Type shown above make PDFBox think it has to use a cross reference stream.
The result is a document whose initial revision ends with a cross reference table and weird trailer entries and whose second revision ends with a cross reference stream. This is not valid.
A work-around
Fortunately, though, understanding how the issue arises presents a work-around: Removing the troublesome trailer entry, e.g. like this:
inputBytes = os.toByteArray();
pdDocument = PDDocument.load(new ByteArrayInputStream(inputBytes));
pdDocument.getDocument().getTrailer().removeItem(COSName.TYPE); // <<<<<<<<<< Remove misleading entry <<<<<<<<<<
With this work-around both revisions in the signed document use cross reference tables and the signature is valid.
Beware, if upcoming PDFBox versions change to save documents loaded from sources with cross reference streams using xref streams, too, the work-around must again be removed.
I would assume, though, that won't happen in the 1.x.x versions to come, and version 2.0.0 will introduce a fundamentally changed API, so the original code won't work out-of-the-box then anyhow.
Other ideas
I tried other ways, too, to circumvent this problem, trying to
store the first manipulation as incremental update, too, or
add the image during the same incremental update as the signature,
cf. SignLikeUnOriginalToo.java, but failed. PDFBox 1.8.9 incremental updates only seem to properly work for adding signatures.
Other ideas revisited
After looking into the creation of additional revisions using PDFBox some more, I tried the other ideas again and now succeeded!
The crucial part is to mark the added and changed objects as updated, including a path from the document catalog.
Applying the first idea (adding the image as an explicit intermediate revision) amounts to this change in doSign:
...
FileOutputStream fos = new FileOutputStream(intermediateDocument);
FileInputStream fis = new FileInputStream(intermediateDocument);
byte inputBytes[] = IOUtils.toByteArray(inputStream);
PDDocument pdDocument = PDDocument.load(new ByteArrayInputStream(inputBytes));
PDJpeg ximage = new PDJpeg(pdDocument, ImageIO.read(logoStream));
PDPage page = (PDPage) pdDocument.getDocumentCatalog().getAllPages().get(0);
PDPageContentStream contentStream = new PDPageContentStream(pdDocument, page, true, true);
contentStream.drawXObject(ximage, 50, 50, 356, 40);
contentStream.close();
pdDocument.getDocumentCatalog().getCOSObject().setNeedToBeUpdate(true);
pdDocument.getDocumentCatalog().getPages().getCOSObject().setNeedToBeUpdate(true);
page.getCOSObject().setNeedToBeUpdate(true);
page.getResources().getCOSObject().setNeedToBeUpdate(true);
page.getResources().getCOSDictionary().getDictionaryObject(COSName.XOBJECT).setNeedToBeUpdate(true);
ximage.getCOSObject().setNeedToBeUpdate(true);
fos.write(inputBytes);
pdDocument.saveIncremental(fis, fos);
pdDocument.close();
pdDocument = PDDocument.load(intermediateDocument);
PDSignature signature = new PDSignature();
...
(as in SignLikeUnOriginalToo.java method doSignTwoRevisions)
Applying the second idea (adding the image as part of the signing revision) amounts to this change in doSign:
...
byte inputBytes[] = IOUtils.toByteArray(inputStream);
PDDocument pdDocument = PDDocument.load(new ByteArrayInputStream(inputBytes));
PDJpeg ximage = new PDJpeg(pdDocument, ImageIO.read(logoStream));
PDPage page = (PDPage) pdDocument.getDocumentCatalog().getAllPages().get(0);
PDPageContentStream contentStream = new PDPageContentStream(pdDocument, page, true, true);
contentStream.drawXObject(ximage, 50, 50, 356, 40);
contentStream.close();
page.getResources().getCOSObject().setNeedToBeUpdate(true);
page.getResources().getCOSDictionary().getDictionaryObject(COSName.XOBJECT).setNeedToBeUpdate(true);
ximage.getCOSObject().setNeedToBeUpdate(true);
PDSignature signature = new PDSignature();
...
(as in SignLikeUnOriginalToo.java method doSignOneStep)
Both variants are clearly preferable to the original approach.

Exporting SWT Image into PDF using Java iText API

I have a an SWT image I want to export this image into a pdf file using iText API.
I have tried saving this image on the disk and then using the path of image to export
it to the pdf, this takes lots of time to generate the pdf.
I have also tried converting the SWT image into AWT image and then exporting it into the
pdf, this approach takes even more time to generate pdf.
Another approach I have been trying is to convert the raw data of image into
jpeg byteArrayOutputStream using ImageLoader Object as shown below :
ImageLoader tempLoader = new ImageLoader();
tempLoader.data = new ImageData[] {
image.getImageData()
};
ByteArrayOutputStream bos = new ByteArrayOutputStream();
tempLoader.save(bos, SWT.IMAGE_JPEG);
Now I am using this ByteArrayOutputStream as input to
OutputStream outStream = new FileOutputStream(selectedPathAndName);
Document document = new Document();
document.setMargins(0,0,0,0);
document.setPageSize(new Rectangle(0,0,width,height));
PdfWriter.getInstance(document, outStream);
document.open();
com.itextpdf.text.Image pdfImage = com.itextpdf.text.Image.getInstance(bos.toByteArray());
document.add(pdfImage);
document.close();
This generates pdf files with the width and height I have set, but the page seems to be empty.
Any suggestions or any other approach is most welcome.
Thank you,
It looks your page sizes are zero, try setting them to something like A4 in the constructor.
Document document = new Document(PageSize.A4, 50, 50, 50, 50);

Categories