How to get the OutputStream of a written PDF from iText - java

I need your help in getting and storing the written PDF from iText in an OutputStream and then to convert it to an InputStream.
The code of writing the PDF is below:
public void CreatePDF() throws IOException {
try{
Document doc = new Document(PageSize.A4, 50, 50, 50, 50);
OutputStream out = new ByteArrayOutputStream();
PdfWriter writer = PdfWriter.getInstance(doc, out);
doc.open();
PdfPTable table = new PdfPTable(1);
PdfPCell cell = new PdfPCell(new Phrase("First PDF"));
cell.setBorder(Rectangle.NO_BORDER);
cell.setRunDirection(PdfWriter.RUN_DIRECTION_LTR);
table.addCell(cell);
doc.add(table);
doc.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
So I am seeking your help to write that PDF in an OutputStream and then to convert it to InputStream.
I need to get the InputStream value so I can pass it to the line for the file download:
StreamedContent file = new DefaultStreamedContent(InputStream, "application/pdf", "xxx.pdf");
Updated Jon Answer:
public InputStream createPdf1() throws IOException {
Document doc = new Document(PageSize.A4, 50, 50, 50, 50);
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
PdfWriter writer;
try {
writer = PdfWriter.getInstance(doc, out);
} catch (DocumentException e) {
}
doc.open();
PdfPTable table = new PdfPTable(1);
PdfPCell cell = new PdfPCell(new Phrase("First PDF"));
cell.setBorder(Rectangle.NO_BORDER);
cell.setRunDirection(PdfWriter.RUN_DIRECTION_LTR);
table.addCell(cell);
doc.add(table);
}
catch ( Exception e)
{
e.printStackTrace();
}
return new ByteArrayInputStream(out.toByteArray());
}

You should change the declaration of out to be of type ByteArrayOutputStream rather than just OutputStream. Then you can call ByteArrayOutputStream.toByteArray() to get the bytes, and construct a ByteArrayInputStream wrapping that.
As an aside, I wouldn't catch Exception like that, and I'd use a try-with-resources statement to close the document, assuming it implements AutoCloseable. It's also a good idea to follow Java naming conventions. So for example, you might have:
public InputStream createPdf() throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
try (Document doc = new Document(PageSize.A4, 50, 50, 50, 50)) {
PdfWriter writer = PdfWriter.getInstance(doc, out);
doc.open();
PdfPTable table = new PdfPTable(1);
PdfPCell cell = new PdfPCell(new Phrase("First PDF"));
cell.setBorder(Rectangle.NO_BORDER);
cell.setRunDirection(PdfWriter.RUN_DIRECTION_LTR);
table.addCell(cell);
doc.add(table);
}
return new ByteArrayInputStream(out.toByteArray());
}

Related

generate zip file grouping multiple pdf, using servlet and itext 7

I'm trying to put multiple generated pdf into a zip from servlet using itext7, I've managed to put one pdf in a zip file but not more. Here is the code:
private void printMore(HttpServletRequest req, HttpServletResponse resp) throws SQLException {
String masterPath = req.getServletContext().getRealPath("/assets/template/templateStatement.pdf");
try (PdfReader reader = new PdfReader(masterPath);
ZipOutputStream zipFile = new ZipOutputStream(resp.getOutputStream());
PdfWriter writer = new PdfWriter(zipFile);
PdfDocument pdf = new PdfDocument(reader, writer);
Document doc = new Document(pdf)) {
List<Student> studentList = getFactoryDAO().getStatementDAO().selectStudentHasBalance();
for (Student student : studentList){
// Generate PDF for the student
PdfPage page = pdf.getPage(1);
PdfCanvas canvas = new PdfCanvas(page);
FontProgram fontProgram = FontProgramFactory.createFont();
PdfFont font = PdfFontFactory.createFont(fontProgram, "utf-8", true);
canvas.setFontAndSize(font, 10);
canvas.beginText();
canvas.setTextMatrix(178, 650); // student code
canvas.showText(student.getS_Code());
canvas.setTextMatrix(200, 610); // Date of Statement
canvas.showText(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
canvas.endText();
float[] pointsWidth = {60f,120f,70f,70f};
Table table = new Table(pointsWidth);
table.setMarginTop(280);
table.setMarginLeft(70);
table.setFont(font);
table.setFontSize(10);
table.setTextAlignment(TextAlignment.CENTER);
//Header Table
table.addCell(new Cell().add("Date Inscription"));
table.addCell(new Cell().add("Name"));
table.addCell(new Cell().add("Fees"));
table.addCell(new Cell().add("Observation"));
//Detail Table
table.addCell(new Cell().add(student.getTxnDate()));
table.addCell(new Cell().add(student.getS_FullName));
table.addCell(new Cell().add(student.getFees));
table.addCell(new Cell().add(student.getObservation));
doc.add(table);
ZipEntry zipEntry = new ZipEntry(student.getS_Code() + "_" + student.getS_LName() + ".pdf");
zipFile.putNextEntry(zipEntry);
//zipFile.write(); Shall I use it?
}
} catch (IOException e) {
e.printStackTrace();
}
resp.setHeader("Content-disposition","attachement; filename=test.zip");
resp.setContentType("application/zip");
}
I've based on this this post and this post but doesn't work. I already check more post like this but the version of itext7 has no PdfWriter.getInstance as mentionned. I've tried more thing but can't managed to go furthermore.
UPDATED :
After Enterman suggestion i updated it like this :
String masterPath = req.getServletContext().getRealPath("/assets/template/templateStatement.pdf");
try (PdfReader reader = new PdfReader(masterPath);
ZipOutputStream zipFile = new ZipOutputStream(resp.getOutputStream());
PdfWriter writer = new PdfWriter(zipFile);
PdfDocument pdf = new PdfDocument(reader, writer)
) {
List<Student> studentList = getFactoryDAO().getStatementDAO().selectStudentHasBalance();
for (Student student : studentList){
try (Document doc = new Document(pdf)){
// Generate PDF for the student
PdfPage page = pdf.getPage(1);
PdfCanvas canvas = new PdfCanvas(page);
FontProgram fontProgram = FontProgramFactory.createFont();
PdfFont font = PdfFontFactory.createFont(fontProgram, "utf-8", true);
canvas.setFontAndSize(font, 10);
canvas.beginText();
canvas.setTextMatrix(178, 650); // student code
canvas.showText(student.getS_Code());
canvas.setTextMatrix(200, 610); // Date of Statement
canvas.showText(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
canvas.endText();
float[] pointsWidth = {60f,120f,70f,70f};
Table table = new Table(pointsWidth);
table.setMarginTop(280);
table.setMarginLeft(70);
table.setFont(font);
table.setFontSize(10);
table.setTextAlignment(TextAlignment.CENTER);
//Header Table
table.addCell(new Cell().add("Date Inscription"));
table.addCell(new Cell().add("Name"));
table.addCell(new Cell().add("Fees"));
table.addCell(new Cell().add("Observation"));
//Detail Table
table.addCell(new Cell().add(student.getTxnDate()));
table.addCell(new Cell().add(student.getS_FullName));
table.addCell(new Cell().add(student.getFees));
table.addCell(new Cell().add(student.getObservation));
doc.add(table);
ZipEntry zipEntry = new ZipEntry(student.getS_Code() + "_" + student.getS_LName() + ".pdf");
zipFile.putNextEntry(zipEntry);
//zipFile.write(); Shall I use it?
}
}
} catch (IOException e) {
e.printStackTrace();
}
resp.setHeader("Content-disposition","attachement; filename=test.zip");
resp.setContentType("application/zip");
But still no luck.
Your help is welcome.
You should try using a FileInputStream, like below (code of my own, working well in production)
private File createZip(List<File> forZip, LocalDate date) {
String zipName = Constants.ORDER_FILE_PATH + date.getYear() +"-" + date.getMonth().getValue() + "-" + date.getMonth().getDisplayName(TextStyle.FULL, Locale.FRENCH) + ".zip";
FileOutputStream fos = null;
try {
fos = new FileOutputStream(zipName);
ZipOutputStream zipOut = new ZipOutputStream(fos);
for (File srcFile : forZip) {
FileInputStream fis = new FileInputStream(srcFile);
ZipEntry zipEntry = new ZipEntry(srcFile.getName());
zipOut.putNextEntry(zipEntry);
byte[] bytes = new byte[1024];
int length;
while((length = fis.read(bytes)) >= 0) {
zipOut.write(bytes, 0, length);
}
fis.close();
//srcFile.delete();
}
zipOut.close();
fos.close();
} catch (IOException e) {
logger.error("createZip", e);
}
return new File(zipName);
}
Special thanks for BenjaminD, Enterman for their support and all stack community.
I post this answer for those who has faced the same problem as me. (I've been stuck for 4 days). "Generating multiple PDF with itext 7 and servlets"
As Enterman said : "need new Instance of Document". In addition need PdfDocument also. And as BenjaminD instruction : "Generate a file PDF first, after put them into a zip".
String masterPath = req.getServletContext().getRealPath("/assets/template/templateStatement.pdf");
try (ZipOutputStream zipOut = new ZipOutputStream(resp.getOutputStream())) {
Liste<File> listFile = new ArrayList<>();
List<Student> studentList = getFactoryDAO().getStatementDAO().selectStudentHasBalance();
for (Student student : studentList){
File file = new File(student.getS_Code()+"_"+new SimpleDateFormat("yyyy-MM-dd").format(new Date())+".pdf");
try (PdfDocument pdf = new PdfDocument(new PdfReader(masterPath), new PdfWriter(file.getName()))
Document doc = new Document(pdf)){
// Generate PDF for the student
PdfPage page = pdf.getPage(1);
PdfCanvas canvas = new PdfCanvas(page);
FontProgram fontProgram = FontProgramFactory.createFont();
PdfFont font = PdfFontFactory.createFont(fontProgram, "utf-8", true);
canvas.setFontAndSize(font, 10);
canvas.beginText();
canvas.setTextMatrix(178, 650); // student code
canvas.showText(student.getS_Code());
canvas.setTextMatrix(200, 610); // Date of Statement
canvas.showText(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
canvas.endText();
float[] pointsWidth = {60f,120f,70f,70f};
Table table = new Table(pointsWidth);
table.setMarginTop(280);
table.setMarginLeft(70);
table.setFont(font);
table.setFontSize(10);
table.setTextAlignment(TextAlignment.CENTER);
//Header Table
table.addCell(new Cell().add("Date Inscription"));
table.addCell(new Cell().add("Name"));
table.addCell(new Cell().add("Fees"));
table.addCell(new Cell().add("Observation"));
//Detail Table
table.addCell(new Cell().add(student.getTxnDate()));
table.addCell(new Cell().add(student.getS_FullName));
table.addCell(new Cell().add(student.getFees));
table.addCell(new Cell().add(student.getObservation));
doc.add(table);
listFile.add(file);
}
}
File zipFile = createZip(listFile,
newSimpleDateFormat("yyyy-MM-dd").format(new Date())); //BenjaminD source in answer
ZipEntry zipEntry = new ZipEntry(zipFile.getName);
zipEntry.putNextEntry(zipEntry);
fileInputStream fis = new FileInputStream(zipFile);
byte[] bytes = new byte[1024];
int length;
while((length = fis.read(bytes)) >= 0) {
zipOut.write(bytes, 0, length);
}
fis.close();
resp.setHeader("Content-disposition","attachement; filename=" + zipFile);
resp.setContentType("application/zip");
} catch (IOException e) {
e.printStackTrace();
}
It will put the zip in a zip (can Directly use FileOutpuStream to not put it again in a zip).
Thank you again.

How can I add a password to a base 64 pdf?

I have this method in which I add a password to the pdf, but I am doing it with pdf from the computer. What I want to try is to receive as input parameter a string that would be pdf in base 64 and respond to a base64.
public static void main(String[] args) {
try {
OutputStream file = new FileOutputStream(new File("D:\\Test.pdf"));
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, file);
writer.setEncryption(USER_PASS.getBytes(), OWNER_PASS.getBytes(),
PdfWriter.ALLOW_PRINTING, PdfWriter.ENCRYPTION_AES_128);
document.open();
document.add(new Paragraph("Hello World, iText"));
document.add(new Paragraph(new Date().toString()));
document.close();
file.close();
} catch (Exception e) {
e.printStackTrace();
}
}
It was complicated how to handle a Base64 pdf because it was the first time, but in the end I was able to develop the method where you can add the password to a pdf that is already in base64.
public String EncriptarPDFconContraseña(String pdfBase64, String passwordUser, String passwordOwner) throws IOException, DocumentException {
PdfReader reader = new PdfReader(Base64.decode(pdfBase64));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PdfStamper stamper = new PdfStamper(reader, baos);
stamper.setEncryption(passwordUser.getBytes(), passwordOwner.getBytes(), PdfWriter.ALLOW_PRINTING, PdfWriter.ENCRYPTION_AES_128);
stamper.close();
String base64 = Base64.encodeBytes(baos.toByteArray());
return base64;
}

Write Heart Symbol in pdf using itext java

Trying to write heart symbol in pdf through java code .
This is my input to pdf : ❤️❤️❤️
But pdf generated is empty without anything written.
Using itext to write to pdf.
The Font used is tradegothic_lt_boldcondtwenty.ttf
OutputStream file = new FileOutputStream(fileName);
Document document = new Document(PageSize.A6);
PdfWriter writer = PdfWriter.getInstance(document, file);
document.open();
PdfLayer nested = new PdfLayer("Layer 1", writer);
PdfContentByte cb = writer.getDirectContent();
cb.beginLayer(nested);
ColumnText ct = new ColumnText(cb);
Font font = getFont();
Phrase para1 = new Phrase("❤️❤️❤️",font);
ct.setSimpleColumn(para1,38,0,260,138,15, Element.ALIGN_LEFT);
ct.go();
cb.endLayer();
document.close();
file.close();
private Font getFont() {
final String methodName = "generatePDF";
LOGGER.entering(CLASSNAME, methodName);
Font font = null;
try {
String filename = tradegothic_lt_boldcondtwenty.ttf;
FontFactory.register(filename, filename);
font = FontFactory.getFont(filename, BaseFont.CP1252, BaseFont.EMBEDDED,11.8f);
} catch(Exception exception) {
LOGGER.logp(Level.SEVERE, CLASSNAME, methodName, "Exception Occurred while fetching the Trade Gothic font." + exception);
font = FontFactory.getFont(FontFactory.HELVETICA_BOLD,11.8f);
}
return font;
}
Phrase para1 has the heart correctly. But not able to see in pdf

Using iText to create PDF

I'm trying to create a PDF using iText and I'm having a great deal of difficulty. In short, what I want to do is:
Read in a template pdf
Make a copy in memory of the template
Draw a table on the copy
Write the copy pdf to an outputstream
So far, it's looking like this
// read in template pdf
InputStream templateStream = getServletContext().getResourceAsStream(labelsTemplate);
PdfReader reader = new PdfReader(templateStream);
// create a table in a new document
Document document = new Document();
PdfCopy copy = new PdfCopy(document, os);
document.open();
PdfPTable table = new PdfPTable(2);
PdfPCell cell;
cell = new PdfPCell(new Phrase("row 1; cell 1"));
table.addCell(cell);
cell = new PdfPCell(new Phrase("row 1; cell 2"));
table.addCell(cell);
document.add(table);
Can someone explain how I can make a copy of the template once I've used PdfReader to read it? Is there a way to write the table onto the template copy and not a new document?
For future references, here's what I've done:
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "inline;filename=\"scheduler-labels.pdf\"");
ServletOutputStream os = response.getOutputStream();
// read in template pdf
InputStream templateStream = getServletContext().getResourceAsStream(labelsTemplate);
PdfReader reader = new PdfReader(templateStream);
// make new pdf document to draw table and output to memory
Document document = new Document(reader.getPageSize(1));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PdfWriter.getInstance(document, baos);
// write table
document.open();
PdfPTable table = new PdfPTable(2);
table.setWidthPercentage(110);
PdfPCell cell;
cell = new PdfPCell(new Phrase("row 1; cell 1"));
table.addCell(cell);
cell = new PdfPCell(new Phrase("row 1; cell 2"));
table.addCell(cell);
cell = new PdfPCell(new Phrase("row 2; cell 1"));
table.addCell(cell);
cell = new PdfPCell(new Phrase("row 2; cell 2"));
table.addCell(cell);
document.add(table);
document.close();
// read in newly generated table pdf
PdfReader tableReader = new PdfReader(baos.toByteArray());
ByteArrayOutputStream baosCombined = new ByteArrayOutputStream();
PdfStamper stamper = new PdfStamper(tableReader, baosCombined);
// get a page from the template pdf
PdfImportedPage page = stamper.getImportedPage(reader, 1);
// add to background of table pdf
PdfContentByte background;
background = stamper.getUnderContent(1);
background.addTemplate(page, 0, 0);
stamper.close();
tableReader.close();
reader.close();
// write to servlet output
baosCombined.writeTo(os);
os.flush();
os.close();
As studying the sample referenced in my comment was just what [Tuan] needed, I formulate it as an answer:
The sample Stationery.java from chapter 6 of iText in Action — 2nd Edition essentially shows how to use the contents of a given PDF as background (stationery-like) of a new PDF while filling its foreground with new content.
The central code is as follows:
public class Stationery extends PdfPageEventHelper
{
[...]
public void createPdf(String filename) throws Exception
{
// step 1
Document document = new Document(PageSize.A4, 36, 36, 72, 36);
// step 2
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
useStationary(writer);
// step 3
document.open();
// step 4
[... add content to PDF ...]
// step 5
document.close();
}
[...]
public void useStationary(PdfWriter writer) throws IOException
{
writer.setPageEvent(this);
PdfReader reader = new PdfReader(STATIONERY);
page = writer.getImportedPage(reader, 1);
}
public void onEndPage(PdfWriter writer, Document document)
{
writer.getDirectContentUnder().addTemplate(page, 0, 0);
}
[...]
}
As implicit close() calls have been removed more and more recently, the PdfReader reader instantiated in useStationary nowerdays should be stored in some variable of Stationery and closed after createPdf has executed.

File not found when inserting image file into PDF using itext

How to add images and design header, footer to pdf using itext?
I have written this ,but getting exception file not found.
Image image = Image.getInstance("\resources\image.gif");
thanks
I used the following code to insert an image from the classpath. Typically useful when you need to include an image that is not accessible from a public url.
Image img = Image.getInstance(getClass().getClassLoader().getResource("MyImage.jpg"));
In my case, I use maven, so I put MyImage.jpg in src/main/resources
take a look at this example
import java.io.*;
import com.lowagie.text.*;
import com.lowagie.text.pdf.*;
public class CreatePDF{
public static void main(String arg[])throws Exception{
try{
Document document=new Document();
FileOutputStream fos=new FileOutputStream("C:/header-footer.pdf");
PdfWriter writer = PdfWriter.getInstance(document, fos);
document.open();
Image image1 = Image.getInstance("C:/image1.jpg");
Image image2 = Image.getInstance("C:/image2.jpg");
image1.setAbsolutePosition(0, 0);
image2.setAbsolutePosition(0, 0);
PdfContentByte byte1 = writer.getDirectContent();
PdfTemplate tp1 = byte1.createTemplate(600, 150);
tp1.addImage(image2);
PdfContentByte byte2 = writer.getDirectContent();
PdfTemplate tp2 = byte2.createTemplate(600, 150);
tp2.addImage(image1);
byte1.addTemplate(tp1, 0, 715);
byte2.addTemplate(tp2, 0, 0);
Phrase phrase1 = new Phrase(byte1 + "", FontFactory.getFont(FontFactory.TIMES_ROMAN, 7, Font.NORMAL));
Phrase phrase2 = new Phrase(byte2 + "", FontFactory.getFont(FontFactory.TIMES_ROMAN, 7, Font.NORMAL));
HeaderFooter header = new HeaderFooter(phrase1, true);
HeaderFooter footer = new HeaderFooter(phrase2, true);
document.setHeader(header);
document.setFooter(footer);
document.close();
System.out.println("File is created successfully showing header and footer.");
}
catch (Exception ex){
System.out.println(ex);
}
}
}

Categories