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

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.

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.

Itext 7.1.16 - adding Two Paragraphs dont work

i try to create PDF Document but i'am not able to Create a Document with 2 Paragraphs.
It just show the first one added:
Here is my code for reproducing:
public void createBillingDocument(List<PDFData> datas) {
datas.forEach(data -> {
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
PdfWriter writer = new PdfWriter(outputStream);
PdfDocument pdf = new PdfDocument(writer);
Document document = new Document(pdf,PageSize.A4);
document.add(new Paragraph("Muh"));
document.add(new Paragraph("Kuh"));
document.close();
pdf.close();
writer.close();
outputStream.close();
fileAccess.storeFile(outputStream.toString(), "test/" + "Name.pdf");
} catch (IOException e) {
throw new RuntimeException(e);
}
});
}
Has anyone the same Problem an found a Solution?
Regards
Edit:
One Strange thing is, if i make a Breake betwenn it both Paragraphs are shown. Each one one Page.
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
PdfWriter writer = new PdfWriter(outputStream);
PdfDocument pdf = new PdfDocument(writer);
Document document = new Document(pdf,PageSize.A4);
document.add(new Paragraph("Muh"));
document.add(new AreaBreak());
document.add(new Paragraph("Kuh"));
document.close();
pdf.close();
writer.close();
outputStream.close();
fileAccess.storeFile(outputStream.toString(), "test/" + "Name.pdf");
} catch (IOException e) {
throw new RuntimeException(e);
}
Ok found out. #mkl was right. The Problem lies somewhere in "save the Document as String". Chaged it to ByteArray and voila it worked :)
Thanks for your Time!

ByteArrayOutputStream size is zero in PDFWriter?

I have been breaking my head from past 1 hour i am not able to solve this issue...i know its easy to write the PDF in java but my outputstream size is zero,... here is my code..
Document document = new Document();
try
{
ByteArrayOutputStream dsf = new ByteArrayOutputStream();
PdfWriter writer = PdfWriter.getInstance(document, dsf);
document.open();
document.add(new Paragraph("Some content here"));
// Set attributes here
document.addAuthor("Lokesh Gupta");
document.addCreationDate();
document.addCreator("HowToDoInJava.com");
document.addTitle("Set Attribute Example");
document.addSubject("An example to show how attributes can be added to pdf files.");
if (frontPageMap != null && !frontPageMap.isEmpty()) {
PdfPTable table = new PdfPTable(frontPageMap.size()); // creating
// columns.
table.setWidthPercentage(100); // Width 100%
table.setSpacingBefore(10f); // Space before table
table.setSpacingAfter(10f); // Space after table
for (Map.Entry<String, Object> entry : frontPageMap.entrySet()) {
PdfPCell tempCell = new PdfPCell(new Paragraph(entry.getKey()));
tempCell.setBorderColor(BaseColor.BLUE);
tempCell.setPaddingLeft(10);
tempCell.setHorizontalAlignment(Element.ALIGN_CENTER);
tempCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
table.addCell(tempCell);
}
document.add(table);
}
System.out.println("Size Of Byte Array is "+dsf.size());
ByteArrayInputStream bInput = new ByteArrayInputStream(dsf.toByteArray());
file = new DefaultStreamedContent(bInput, "pdf", fileName);
document.close();
writer.close();
NOTE:I am able to print map key values also but When i download PDF the size is zero.
Maybe you should finish creating the PDF (with document.close() and writer.close()), before you try to access the contents:
//Finish writing the PDF
document.close();
writer.close();
//now check what's been written:
System.out.println("Size Of Byte Array is "+dsf.size());
ByteArrayInputStream bInput = new ByteArrayInputStream(dsf.toByteArray());
file = new DefaultStreamedContent(bInput, "pdf", fileName);
document.close();
writer.close();
ByteArrayInputStream bInput = new ByteArrayInputStream(dsf.toByteArray());
file = new DefaultStreamedContent(bInput, "pdf", fileName);
System.out.println("Size Of Byte Array is "+dsf.size());
Add this code. Here you finish writing the pdf file and then you can print the size of the file. The size my be zero according to the content , but the pdf file generated should have all the records written in it ... Cheers :)

Vaadin Convert and display image as PDF

Does anyone know how image file can be easily converted into PDF format. What I need is to get the image from database and display it on the screen as PDF. What am I doing wrong? I tried to use iText but with no results.
My code:
StreamResource resource = file.downloadFromDatabase();//get file from db
Document converToPdf=new Document();//Create Document Object
PdfWriter.getInstance(convertToPdf, new FileOutputStream(""));//Create PdfWriter for Document to hold physical file
convertToPdf.open();
Image convertJpg=Image.getInstance(resource); //Get the input image to Convert to PDF
convertToPdf.add(convertJpg);//Add image to Document
Embedded pdf = new Embedded("", convertToPdf);//display document
pdf.setMimeType("application/pdf");
pdf.setType(Embedded.TYPE_BROWSER);
pdf.setSizeFull();
Thanks.
You're not using iText correctly:
You never close your writer, so the addition of the image never gets written to the outputstream.
You pass an empty string to your FileOutputStream. If you want to keep the pdf in memory, use a ByteArrayOutputStream. If not, define a temporary name instead.
You pass your Document object, which is a iText-specific object to your Embedded object and treat it like a file. It is not a pdf-file or byte[]. You'll probably want to pass either your ByteArrayOutputStream or read the temp file as a ByteArrayOutputStream into memory and pass that to Embedded.
Maybe someone will use (Vaadin + iText)
Button but = new Button("FV");
StreamResource myResource = getPDFStream();
FileDownloader fileDownloader = new FileDownloader(myResource);
fileDownloader.extend(but);
hboxBottom.addComponent( but );
private StreamResource getPDFStream() {
StreamResource.StreamSource source = new StreamResource.StreamSource() {
public InputStream getStream() {
// step 1
com.itextpdf.text.Document document = new com.itextpdf.text.Document();
// step 2
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
com.itextpdf.text.pdf.PdfWriter.getInstance(document, baos);
// step 3
document.open();
document.add(Chunk.NEWLINE); //Something like in HTML :-)
document.add(new Paragraph("TEST" ));
document.add(Chunk.NEWLINE); //Something like in HTML :-)
document.newPage(); //Opened new page
//document.add(list); //In the new page we are going to add list
document.close();
//file.close();
System.out.println("Pdf created successfully..");
} catch (DocumentException ex) {
Logger.getLogger(WndOrderZwd.class.getName()).log(Level.SEVERE, null, ex);
}
ByteArrayOutputStream stream = baos;
InputStream input = new ByteArrayInputStream(stream.toByteArray());
return input;
}
};
StreamResource resource = new StreamResource ( source, "test.pdf" );
return resource;
}

iText rotate() won't orient the first page

Everything I have read regarding iText says you should be able to set the page size and then create a new page. But for some reason when I try this my first page isn't rotated. But my second is. Any ideas?
response.setContentType("application/pdf");
Document document = new Document();
try{
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
PdfWriter.getInstance(document, buffer);
document.open();
//Start a new page
document.setPageSize(PageSize.LETTER.rotate()); // 11" x 8.5" new Rectangle(792f, 612f)
document.newPage();
Paragraph topText = new Paragraph();
// add some content here...
document.close();
DataOutput dataOutput = new DataOutputStream(response.getOutputStream());
byte[] bytes = buffer.toByteArray();
response.setContentLength(bytes.length);
for(int i = 0; i < bytes.length; i++) {
dataOutput.writeByte(bytes[i]);
}
} catch (DocumentException e) {
e.printStackTrace();
}
document.newPage() really means "finish the current page and open a new one". This implies that after you open() a document, you already have a blank page (with whatever size the document had set before) ready.
You should set your page size before opening the document:
document.setPageSize(PageSize.LETTER.rotate());
document.open();

Categories

Resources