saving a file fiormat pdf file with java - java

I am trying to create a pdf file then save it to device using fileChooser
It works the saving but when i go to the file to open it it doesn't open
here is my code
FileChooser fc = new FileChooser();
fc.getExtensionFilters().add(new FileChooser.ExtensionFilter("PDF File", "*.pfd"));
fc.setTitle("Save to PDF"
);
fc.setInitialFileName("untitled.pdf");
Stage stg = (Stage) ((Node) event.getSource()).getScene().getWindow();
File file = fc.showSaveDialog(stg);
if (file != null) {
String str = file.getAbsolutePath();
FileOutputStream fos = new FileOutputStream(str);
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(str));
document.open();
document.add(new Paragraph("A Hello World PDF document."));
document.close();
writer.close();
fos.flush();
}
when i open it this is the error showing it says the file is either opened or used by another user

Your code does not close() the FileOutputStream which may cause a resource leak and the document is not properly accessible, maybe even corrupted.
When you work with a FileOutputStream that implements AutoClosable, you have two options:
close() the FileOutputStream manually:
FileChooser fc = new FileChooser();
fc.getExtensionFilters().add(new FileChooser.ExtensionFilter("PDF File", "*.pfd"));
fc.setTitle("Save to PDF");
fc.setInitialFileName("untitled.pdf");
Stage stg = (Stage) ((Node) event.getSource()).getScene().getWindow();
File file = fc.showSaveDialog(stg);
if (file != null) {
String str = file.getAbsolutePath();
FileOutputStream fos = new FileOutputStream(str);
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(str));
document.open();
document.add(new Paragraph("A Hello World PDF document."));
document.close();
writer.close();
fos.flush();
/*
* ONLY DIFFERENCE TO YOUR CODE IS THE FOLLOWING LINE
*/
fos.close();
}
}
or use a try with resources read about that in this post, for example.

Related

ExceptionConverter: java.io.IOException: Stream Closed when trying to create a PDF using iText

I'm working on PDF related project and I want to create a PDF from the existing PDF.
all things are done but when I created a final PDF at that time this exception was thrown at the line of document.close(); at the method of savePDF which describe below.
Create new PDF from existing PDF adding PdfImportedPage.
here is my code
The app crashes only when we add a new page
private void createAndAddPage(Bitmap bitmap) {
try {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
Document document = new Document();
File file = getPdfFile();
FileOutputStream fileOutputStream = new FileOutputStream(file);
PdfWriter pdfWriter = PdfWriter.getInstance(document, fileOutputStream); // Change pdf's name.
document.open();
Image image = Image.getInstance(byteArray); // Change image's name and extension.
float scaler = ((document.getPageSize().getWidth() - document.leftMargin()
- document.rightMargin() - 0) / image.getWidth()) * 100; // 0 means you have no indentation. If you have any, change it.
image.scalePercent(scaler);
image.setAlignment(Image.ALIGN_CENTER);
document.add(image);
document.close();
PdfReader pdfReader = new PdfReader(file.getPath());
PdfImportedPage pdfImportedPage = pdfWriter.getImportedPage(pdfReader, 1);
pageAdjustmentAdapter.AddPage(new PageAjdustAdapter.PdfPage(pdfImportedPage, bitmap));
} catch (Exception e) {
e.printStackTrace();
}
}
method when saves a final PDF(crash happens in this method)
private void savePDF(PageAjdustAdapter pageAdjustment) {
mPDFpages = pageAdjustment.getUpdatedList();
try {
pdfWriter.setPageEvent(new RotateEvent());
document.open();
PdfContentByte pdfContentByte = pdfWriter.getDirectContent();
for (int i = 0; i < mPDFpages.size(); i++) {
pdfContentByte.addTemplate(mPDFpages.get(i).page, 0, 0);
document.newPage();
}
} catch (Exception e) {
Log.d(TAG, "run: -> " + e.getMessage());
e.printStackTrace();
} finally {
if (document.isOpen()) document.close();
actionListener.onEnd("Success");
}
}
logcat
ExceptionConverter: java.io.IOException: Stream Closed
at java.io.FileOutputStream.write(FileOutputStream.java:391)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
at java.io.BufferedOutputStream.write(BufferedOutputStream.java:121)
at java.io.FilterOutputStream.write(FilterOutputStream.java:103)
at com.itextpdf.text.pdf.OutputStreamCounter.write(OutputStreamCounter.java:104)
at com.itextpdf.text.pdf.PRStream.toPdf(PRStream.java:244)
at com.itextpdf.text.pdf.PdfIndirectObject.writeTo(PdfIndirectObject.java:157)
at com.itextpdf.text.pdf.PdfWriter$PdfBody.write(PdfWriter.java:402)
at com.itextpdf.text.pdf.PdfWriter$PdfBody.add(PdfWriter.java:380)
at com.itextpdf.text.pdf.PdfWriter$PdfBody.add(PdfWriter.java:359)
at com.itextpdf.text.pdf.PdfWriter.addToBody(PdfWriter.java:854)
at com.itextpdf.text.pdf.PdfReaderInstance.writeAllVisited(PdfReaderInstance.java:160)
at com.itextpdf.text.pdf.PdfReaderInstance.writeAllPages(PdfReaderInstance.java:176)
at com.itextpdf.text.pdf.PdfWriter.addSharedObjectsToBody(PdfWriter.java:1368)
at com.itextpdf.text.pdf.PdfWriter.close(PdfWriter.java:1251)
at com.itextpdf.text.pdf.PdfDocument.close(PdfDocument.java:901)
at com.itextpdf.text.Document.close(Document.java:415)
at com.mobilix.docscanner.PageAdjustment$8.run(PageAdjustment.java:233)
at java.lang.Thread.run(Thread.java:923)
In createAndAddPage you import the page into the wrong PdfWriter:
Document document = new Document();
File file = getPdfFile();
FileOutputStream fileOutputStream = new FileOutputStream(file);
PdfWriter pdfWriter = PdfWriter.getInstance(document, fileOutputStream); // Change pdf's name.
document.open();
[...]
document.close();
PdfReader pdfReader = new PdfReader(file.getPath());
PdfImportedPage pdfImportedPage = pdfWriter.getImportedPage(pdfReader, 1);
Here you import the new page into the PdfWriter used for creating that same new page. You instead have to import it into the PdfWriter in which you eventually want to use the pdfImportedPage.

How to generate a pdf to a variable instead of a file?

I am creating a pdf file and storing it in a directory. I now want to pass back the pdf data so the user can download it to their preferred directory (i.e., no longer create the file in the directory). How do I create the "pdfData" to pass back please?
I understand that it would involve replaceing "new FileOutputStream(FILE)" with the name of the variable to store the data in; however, I can not work it out or find an example online.
I have:
String filePath = System.getProperty("user.home") + "\\Documents\\"+fileName; //Test use
Document document = new Document(PageSize.A4, 72f, 72f, 72f, 72f);
try {
PdfWriter.getInstance(document, new FileOutputStream(FILE));
document.open();
addMetaData(document);
addImages(document);
addTitlePage(document, recipeDetails, recipeName, servings, servingSize);
document.close();
} catch (Exception e) {
e.printStackTrace();
}
//return pdfData;
To show what mkl suggested merged in with your code:
String filePath = System.getProperty("user.home") + "\\Documents\\"+fileName; //Test use
Document document = new Document(PageSize.A4, 72f, 72f, 72f, 72f);
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PdfWriter.getInstance(document, baos);
document.open();
addMetaData(document);
addImages(document);
addTitlePage(document, recipeDetails, recipeName, servings, servingSize);
document.close();
byte[] pdfData = baos.toByteArray();
return pdfData;
} catch (Exception e) {
e.printStackTrace();
}
The pdfData is a byte[] (byte array). This can be directly streamed/stored anywhere as the actual pdf. Just keep in mind that this is writing the PDF into memory, so you have scalability issue if doing lots of large PDFs concurrently.
I hope that helps.

How to save created file to the user specified filepath in Java?

This might be common question, but I didn't found exact solution.
I have a JavaFX application which creates PDF file (using iText 7) using data from cloud sql server.
However, this file is now saved in my specified file path.
I want my user to specify where he/she wants to save that file.
String dest = "itextData//singleLR.pdf";
PdfWriter writer = new PdfWriter(dest);
PdfDocument pdf = new PdfDocument(writer);
Document document = new Document(pdf);
Now here, the path dest is already specified. I want it to be specified by user.
Expected output
//File browsing code on button click
//Got String in variable user_specified_path
String dest = user_specified_path;
PdfWriter writer = new PdfWriter(dest);
PdfDocument pdf = new PdfDocument(writer);
Document document = new Document(pdf);
As suggested by #VGR , I used JavaFX FileChooser.
However, instead of fileChooser.showOpenDialog(scene) , I used fileChooser.showSaveDialog(scene);
showOpenDialog() is used to open existing file.
showSaveDialog() is used to create new file
So my code goes like below,
print.setOnAction(event -> {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Save PDF File");
fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("PDF File", "*.pdf"));
File selectedFile = fileChooser.showSaveDialog(print.getScene().getWindow());
if (selectedFile != null) {
String dest = selectedfile.getAbsolutePath();
PdfWriter writer = new PdfWriter(dest);
PdfDocument pdf = new PdfDocument(writer);
Document document = new Document(pdf);
//DOCUMENT WRITING CODE BEGINS
}
}
For reference -> Saving File with FileChooser in JavaFX

Removing all embedded files in iTextSharp

As I've become interested in iTextSharp I need to learn C#. Since I know a bit of AutoHotkey (simple yet powerful script programming language for Windows) it is easer for me. However, I often come across code written in Java which is said to be easily converted to C#. Unfortunetly, I have some problems with it. Let's have a look at original code written by Bruno Lowagie.
public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
PdfDictionary root = reader.getCatalog();
PdfDictionary names = root.getAsDict(PdfName.NAMES);
names.remove(PdfName.EMBEDDEDFILES);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
stamper.close();
}
This is what I have managed to write on my own:
static void removeFiles(string sourceFilePath, string destFilePath)
{
try
{
// read src file
FileStream inputStream = new FileStream(sourceFilePath, FileMode.Open, FileAccess.Read, FileShare.None);
Document source = new Document();
// open for reading
PdfWriter reader = PdfReader.GetInstance(inputStream);
source.Open();
// create dest file
FileStream outputStream = new FileStream(destFilePath, FileMode.Create, FileAccess.ReadWrite, FileShare.None);
Document dest = new Document();
PdfWriter writer = PdfWriter.GetInstance(dest, inputStream); // open stream from src
// remove embedded files from dest
PdfDictionary root = dest.getCatalog().getPdfObject();
PdfDictionary names = root.getAsDictionary(PdfName.Names);
names.remove(PdfName.EmbeddedFiles);
// close all
source.Close();
dest.Close();
}
catch (Exception ex)
{
}
}
Unfortunately, there are many errors such as:
'Document' does not contain a definition for 'getCatalog' and no extension method 'getCatalog'
'PdfReader' does not contain a definition for 'GetInstance'
This is what I have managed to do after countless hours of coding and googling.
There are some iTextSharp examples available. See for instance: How to read a PDF Portfolio using iTextSharp
I don't know much about C#, but this is a first attempt to fix your code:
static void RemoveFiles(string sourceFilePath, string destFilePath)
{
// read src file
FileStream inputStream = new FileStream(sourceFilePath, FileMode.Open, FileAccess.Read, FileShare.None);
// open for reading
PdfReader reader = new PdfReader(inputStream);
FileStream outputStream = new FileStream(destFilePath, FileMode.Create, FileAccess.ReadWrite, FileShare.None);
PdfStamper stamper = new PdfStamper(reader, outputStream);
// remove embedded files
PdfDictionary root = reader.Catalog;
PdfDictionary names = root.GetAsDict(PdfName.NAMES);
names.Remove(PdfName.EMBEDDEDFILES);
// close all
stamper.Close();
reader.Close();
}
Note that I don't understand why you were using Document and PdfWriter. You should use PdfStamper instead. Also: you are only removing the document-level attachments. If there are file attachment annotations, they will still be present in the PDF.

function that can use iText to concatenate / merge pdfs together - causing some issues

I'm using the following code to merge PDFs together using iText:
public static void concatenatePdfs(List<File> listOfPdfFiles, File outputFile) throws DocumentException, IOException {
Document document = new Document();
FileOutputStream outputStream = new FileOutputStream(outputFile);
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
document.open();
PdfContentByte cb = writer.getDirectContent();
for (File inFile : listOfPdfFiles) {
PdfReader reader = new PdfReader(inFile.getAbsolutePath());
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
document.newPage();
PdfImportedPage page = writer.getImportedPage(reader, i);
cb.addTemplate(page, 0, 0);
}
}
outputStream.flush();
document.close();
outputStream.close();
}
This usually works great! But once and a while, it's rotating some of the pages by 90 degrees? Anyone ever have this happen?
I am looking into the PDFs themselves to see what is special about the ones that are being flipped.
There are errors once in a while because you are using the wrong method to concatenate documents. Please read chapter 6 of my book and you'll notice that using PdfWriter to concatenate (or merge) PDF documents is wrong:
You completely ignore the page size of the pages in the original document (you assume they are all of size A4),
You ignore page boundaries such as the crop box (if present),
You ignore the rotation value stored in the page dictionary,
You throw away all interactivity that is present in the original document, and so on.
Concatenating PDFs is done using PdfCopy, see for instance the FillFlattenMerge2 example:
Document document = new Document();
PdfCopy copy = new PdfSmartCopy(document, new FileOutputStream(dest));
document.open();
PdfReader reader;
String line = br.readLine();
// loop over readers
// add the PDF to PdfCopy
reader = new PdfReader(baos.toByteArray());
copy.addDocument(reader);
reader.close();
// end loop
document.close();
There are other examples in the book.
In case anyone is looking for it, using Bruno Lowagie's correct answer above, here is the version of the function that does not seem to have the page flipping issue i described above:
public static void concatenatePdfs(List<File> listOfPdfFiles, File outputFile) throws DocumentException, IOException {
Document document = new Document();
FileOutputStream outputStream = new FileOutputStream(outputFile);
PdfCopy copy = new PdfSmartCopy(document, outputStream);
document.open();
for (File inFile : listOfPdfFiles) {
PdfReader reader = new PdfReader(inFile.getAbsolutePath());
copy.addDocument(reader);
reader.close();
}
document.close();
}

Categories

Resources