making pdf as password protected with java - java

I want to make an existing PDF as password protected for which I'm using the itext I am following this URL
http://howtodoinjava.com/2014/07/29/create-pdf-files-in-java-itext-tutorial/
I have developed a program which will send the mail with the PDF as attachment. Below is the code where I am making the PDF file as password protected.
Right now the PDF file is attached in mail but when I am trying to open it, I get an error that it is damaged.
What am I doing wrong in the code below?
// attachment part
MimeBodyPart attachPart = new MimeBodyPart();
String filename = "c:\\SettingupRulesin outlook2003.pdf";
//OutputStream file = new FileOutputStream(new File("PasswordProtected.pdf"));
final OutputStream os = new FileOutputStream(filename);
com.itextpdf.text.Document doc = new com.itextpdf.text.Document();
PdfWriter writer = PdfWriter.getInstance(doc, os);
writer.setEncryption(USER_PASSWORD.getBytes(),
OWNER_PASSWORD.getBytes(), PdfWriter.ALLOW_PRINTING,
PdfWriter.ENCRYPTION_AES_128);
os.close();
DataSource source = new FileDataSource(filename);
attachPart.setDataHandler(new DataHandler(source));
attachPart.setFileName(filename);

You use a PdfWriter. That class can be used to create new PDFs from scratch, not to manipulate existing ones. Please use a PdfStamper instead which is for manipulating existing documents.

Related

Itext generated PDF document to S3 server

I am trying to setup a website where you can "finish order" and then the order is generated in PDF-format. Then I need the pdf-file to be uploaded directly to my S3-bucket
I am fairly new to this so I don't know where to start.
Right now I have made some test code where I make a PDF file with "test" in it.
I have already made an image uploader with my S3-bucket, so I am familiar with how that works.
PdfWriter.getInstance(document, new FileOutputStream("PATH");
document.open();
document.add(new Paragraph("Test");
document.close();
What I want to know is: How do I take this document object and parse it to an S3 server? I have searched everywhere and can't find anything.
Your help is highly appreciated. Thanks!
I have implemented for me. content is byte[] of uploading file
final ObjectMetadata metadata = new ObjectMetadata();
metadata.setSSEAlgorithm(ObjectMetadata.AES_256_SERVER_SIDE_ENCRYPTION);
metadata.setContentType(contentType);
metadata.setContentLength(content.length);
final String md5Hex = DigestUtils.md5Hex(new BufferedInputStream(new ByteArrayInputStream(content)));
final PutObjectRequest putObjectRequest = new PutObjectRequest("bucketName", "folderName" + "/" + md5Hex,
new BufferedInputStream(new ByteArrayInputStream(content)), metadata);
final PutObjectResult s3Result = AmazonS3ClientBuilder.defaultClient().putObject(putObjectRequest);

How to open a PdfADocument from an existing PdfDocument in itext7?

In order to check uploaded PDF files for basic PDF/A conformance, I need to read them in as PdfADocuments.
But starting with version 7.1.6 this no longer works, but throws a PdfException(PdfException.PdfReaderHasBeenAlreadyUtilized)
class Controller
...
// get uploaded data into PdfDocument, which is passed
// on to different services.
InputStream filecontent = fileupload.getInputStream();
int read = 0;
byte[] bytes = new byte[1024];
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
while ((read = filecontent.read(bytes,0,bytes.length)) != -1) {
filesize += read;
buffer.write(bytes, 0, read);
}
ByteArrayInputStream input = new ByteArrayInputStream(buffer.toByteArray());
PdfReader reader = new PdfReader(input);
PdfWriter writer = new PdfWriter(new ByteArrayOutputStream());
PdfDocument pdf = new PdfDocument(reader, writer);
AnalyzerService analyzer = new AnalyzerService();
if(analyzer.analyze(pdf)) {
otherService.doSomethingWith(pdf);
}
...
class AnalyzerService
...
public boolean analyze(PdfDocument pdf) {
PdfADocument pdfa = new PdfADocument(
pdf.getReader(), pdf.getWriter() <-- PdfException here
);
...
}
Up to and including iText 7.1.5 this worked.
With 7.1.6 I get "com.itextpdf.kernel.PdfException: Given PdfReader instance has already been utilized. The PdfReader cannot be reused, please create a new instance."
It seems that I need to get the Bytes from the PdfDocument as a byte[], then create a new PdfReader from it. I have tried getting them from the pdf.getReader().getOutputStream().toByteArray(), but that doesn't work.
I'm quite lost at the moment on how to create that PdfADocument from the given PdfDocument.
Your approach uses the same PdfReader and (even worse) the same PdfWriter for both a PdfDocument and a PdfADocument instance. As both can manipulate the PdfReader and write to the PdfWriter, that situation is likely to result in garbage in the writer, so you shall not do this.
Simply always consider a document with both a reader and a writer as work-in-progress, something one cannot treat as a finished document file, e.g. extract for intermediary checks.
As you want to check uploaded PDF files, why don't you simply forward the byte[] from buffer.toByteArray() to the analyze method to create a separate reader (and, if need be, a document) from? This indeed exactly would check the uploaded file...
Furthermore, if your input document may be PDF/A conform and is treated specially in that case, shouldn't you also manipulate it as a PdfADocument if it is? I.e. shouldn't you first check in your analyzer for conformance and in the positive case use a PdfADocument for it also in your controller class?
PdfDocument SourcePDF=null;
PdfADocument DisPDF =null;
try
{
PdfReader Reader = new PdfReader(input-Path);
PdfWriter writer = new PdfWriter(output-Path, new WriterProperties().SetPdfVersion(PdfVersion.PDF_2_0));
writer.SetSmartMode(true);
SourcePDF = new PdfDocument(Reader);
DisPDF = new PdfADocument(writer, PdfAConformanceLevel.PDF_A_3A,
new PdfOutputIntent("Custom", "", "https://www.color.org", "sRGB", new MemoryStream(Properties.Resources.sRGB_CS_profiles)));
DisPDF.InitializeOutlines();
//Setting some required parameters
DisPDF.SetTagged();
DisPDF.GetCatalog().SetLang(new PdfString("en-EN"));
DisPDF.GetCatalog().SetViewerPreferences(new PdfViewerPreferences().SetDisplayDocTitle(true));
PdfMerger merger = new PdfMerger(DisPDF, true, true);
merger.Merge(SourcePDF, 1, sorsePDF.GetNumberOfPages());
SourcePDF.Close();
DisPDF.Close();
}
catch (Exception ex)
{
throw;
}

issue with writing multipart(embedded image) mimeMessage to .html file

I need to write email content from hbase to .html file format. I have all data of email in java object. I am using java.email lib for this. However facing issue with writing multipart image MimeMessage to .html file.
I have image embedded in html as follows. I tried different approach without datasource those are the commented lines in below code.
MimeMessage mimeMessage = outlookMsg.toMimeMessage();
mimeMessage.setFrom("abc#gmail.com");
mimeMessage.setRecipients(RecipientType.TO, "xyz#gmail.com");
mimeMessage.setSubject("story completion");
MimeMultipart multipart = new MimeMultipart("related");
// first part (the html)
MimeBodyPart messageBodyPart = new MimeBodyPart();
String htmlText = "<H1>Hello</H1><img src=\"cid:image\"/>";
messageBodyPart.setContent(htmlText, "text/html");
// add it
multipart.addBodyPart(messageBodyPart);
// second part (the image)
messageBodyPart = new MimeBodyPart();
DataSource fds = new FileDataSource(new File("D:\\JAVA\\Practice_Workspace\\pst\\krishna_radha.jpg"));
messageBodyPart.setDataHandler(new DataHandler(fds));
//messageBodyPart.setHeader("Content-ID", "<image>");
messageBodyPart.setContentID("<image>");
messageBodyPart.setDisposition(MimeBodyPart.INLINE);
//messageBodyPart.attachFile("D:\\JAVA\\Practice_Workspace\\pst\\krishna_radha.jpg");
mimeMessage.setContent(multipart);
File file = new File("D:\\JAVA\\Practice_Workspace\\pst\\htmlemail.html");
//OutputStream os = new FileOutputStream(file);
FileOutputStream os = new FileOutputStream(file);
mimeMessage.writeTo(os);
os.flush();
os.close();
I am getting output as below. Image is not getting displayed.
Please help. Thanks in advance.
enter image description here

iText difference between PdfCopy and PdfACopy

I wrote a function to embed a file as attachment inside a PDF/A-3a document using iText 5.5.13 (using instructions from iText tutorials).
If I attach the file using the class PdfCopy, the result is a correct PDF file, but it does not claim to be PDF/A (maybe it matches all the requirements, but it doesn't say).
If I do the same using PdfACopy, I get an wrongly built document:
InvalidPdfException: Rebuild failed: trailer not found.; Original
message: PDF startxref not found.
Here is my code a little simplified. Commented is the line to use a PdfCopy instead.
public static File embedFile(File inputPdf) {
File outputPdf = new File("./test.pdf");
PdfReader reader = new PdfReader(inputPdf.getAbsolutePath());
Document document = new com.itextpdf.text.Document();
OutputStream os = new FileOutputStream(outputPdf.getAbsolutePath());
PdfACopy copy = new PdfACopy(document, os, PdfAConformanceLevel.PDF_A_3A); // Output doc doesn't work
// PdfCopy copy = new PdfCopy(document, os); // Output doc works but doesn't claim to be PDF/A
document.open();
copy.addDocument(reader);
// Include attachment (extactly as in the sample tutorial)
PdfDictionary parameters = new PdfDictionary();
parameters.put(PdfName.MODDATE, new PdfDate());
PdfFileSpecification fileSpec = PdfFileSpecification.fileEmbedded(
writer, "./src/main/resources/com/itextpdf/invoice.xml",
"invoice.xml", null, "application/xml", parameters, 0);
fileSpec.put(new PdfName("AFRelationship"), new PdfName("Data"));
writer.addFileAttachment("invoice.xml", fileSpec);
PdfArray array = new PdfArray();
array.add(fileSpec.getReference());
writer.getExtraCatalog().put(new PdfName("AF"), array);
os.flush();
reader.close();
document.close();
os.close();
copy.close();
return outputPdf;
}
The input file is already a PDF/A-3a document, so I think I don't need to redefine all the required things like embedded fonts, output intent...
Is there maybe a missing step that is mandatory when using PdfACopy that is not required with PdfCopy?
Would it help to try with iText 7?
Many thanks in advance!
As pointed by Bruno Lowagie in the comments, this is possible with iText 7. Here the function in case it helps someone:
public static File embedFile(File inputPdf, File embeddedFile, String embeddedFileName, String embeddedFileMimeType)
throws IOException {
File outputPdf = new File("./test.pdf");
PdfReader reader = new PdfReader(inputPdf.getAbsolutePath());
PdfWriter writer = new PdfWriter(outputPdf.getAbsolutePath());
PdfADocument pdfDoc = new PdfADocument(reader, writer);
// Add attachment
PdfDictionary parameters = new PdfDictionary();
parameters.put(PdfName.ModDate, new PdfDate().getPdfObject());
PdfFileSpec fileSpec = PdfFileSpec.createEmbeddedFileSpec(pdfDoc, embeddedFile.getAbsolutePath(), embeddedFileName,
embeddedFileName, new PdfName(embeddedFileMimeType), parameters, PdfName.Data);
fileSpec.put(new PdfName("AFRelationship"), new PdfName("Data"));
pdfDoc.addFileAttachment(embeddedFileName, fileSpec);
PdfArray array = new PdfArray();
array.add(fileSpec.getPdfObject().getIndirectReference());
pdfDoc.getCatalog().put(new PdfName("AF"), array);
pdfDoc.close();
reader.close();
writer.close();
return outputPdf;
}

Convert Outputstream to file

Well i'm stucked with a problem,
I need to create a PDF with a html source and i did this way:
File pdf = new File("/home/wrk/relatorio.pdf");
OutputStream out = new FileOutputStream(pdf);
InputStream input = new ByteArrayInputStream(build.toString().getBytes());//Build is a StringBuilder obj
Tidy tidy = new Tidy();
Document doc = tidy.parseDOM(input, null);
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(doc, null);
renderer.layout();
renderer.createPDF(out);
out.flush();
out.close();
well i'm using JSP so i need to download this file to the user not write in the server...
How do I transform this Outputstream output to a file in the java without write this file in hard drive ?
If you're using VRaptor 3.3.0+ you can use the ByteArrayDownload class. Starting with your code, you can use this:
#Path("/download-relatorio")
public Download download() {
// Everything will be stored into this OutputStream
ByteArrayOutputStream out = new ByteArrayOutputStream();
InputStream input = new ByteArrayInputStream(build.toString().getBytes());
Tidy tidy = new Tidy();
Document doc = tidy.parseDOM(input, null);
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(doc, null);
renderer.layout();
renderer.createPDF(out);
out.flush();
out.close();
// Now that you have finished, return a new ByteArrayDownload()
// The 2nd and 3rd parameters are the Content-Type and File Name
// (which will be shown to the end-user)
return new ByteArrayDownload(out.toByteArray(), "application/pdf", "Relatorio.pdf");
}
A File object does not actually hold the data but delegates all operations to the file system (see this discussion).
You could, however, create a temporary file using File.createTempFile. Also look here for a possible alternative without using a File object.
use temporary files.
File temp = File.createTempFile(prefix ,suffix);
prefix -- The prefix string defines the files name; must be at least three characters long.
suffix -- The suffix string defines the file's extension; if null the suffix ".tmp" will be used.

Categories