iText direct Printing

20,416

Solution 1

There's a theoretical and a practical answer to this question.

Let's start with the theoretical answer. There's a Java class called PrintStream that allows you to send an OutputStream to a printer:

Printstream extends FilterOutputStream extends OutputStream

A PrintStream adds functionality to another output stream, namely the ability to print representations of various data values conveniently. Two other features are provided as well. Unlike other output streams, a PrintStream never throws an IOException; instead, exceptional situations merely set an internal flag that can be tested via the checkError method. Optionally, a PrintStream can be created so as to flush automatically; this means that the flush method is automatically invoked after a byte array is written, one of the println methods is invoked, or a newline character or byte ('\n') is written.

So, suppose that you would like to create a PDF in memory and write it to a printer, you'd do something like this:

ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos);
Document document = new Document();
PdfWriter.getInstance(document, ps);
document.open();
// add content
document.close();

As PrintStream extends OutputStream and as PdfWriter accepts any type of OutputStream, you are writing the PDF bytes to the printer and if you want the PDF bytes, you can do baos.toByteArray().

However, the code snippet above sends PDF bytes to the printer. Chances are that your printer doesn't understand PDF and just prints out stuff like:

PDF-1.4
%âãÏÓ
2 0 obj
<</Length 64/Filter/FlateDecode>>stream
*binary stuff*
endstream
endobj
4 0 obj
<</Parent 3 0 R/Contents 2 0 R/Type/Page/Resources<</Font<</F1 1 0 R>>>>
/MediaBox[0 0 595 842]>>
endobj
1 0 obj
<</BaseFont/Helvetica/Type/Font/Encoding/WinAnsiEncoding/Subtype/Type1>>
endobj
3 0 obj
<</Type/Pages/Count 1/Kids[4 0 R]>>
endobj
5 0 obj
<</Type/Catalog/Pages 3 0 R>>
endobj
6 0 obj
<</Producer(iText® 5.4.2 ©2000-2012 1T3XT BVBA \(AGPL-version\))
/ModDate(D:20130502165150+02'00')/CreationDate(D:20130502165150+02'00')>>
endobj
xref
0 7
0000000000 65535 f 
0000000302 00000 n 
0000000015 00000 n 
0000000390 00000 n 
0000000145 00000 n 
0000000441 00000 n 
0000000486 00000 n 
trailer
<</Root 5 0 R/ID [<91bee3a87061eb2834fb6a3258bf817e><91bee3a87061eb2834fb6a3258bf817e>]
/Info 6 0 R/Size 7>>
%iText-5.4.2
startxref
639
%%EOF

Update:

In a comment, the following link was added: https://blog.idrsolutions.com/2010/01/printing-pdf-files-from-java/

This is actually a better way to print your file:

FileInputStream fis = new FileInputStream(“C:/mypdf.pdf”);
Doc pdfDoc = new SimpleDoc(fis, null, null);
DocPrintJob printJob = printService.createPrintJob();
printJob.print(pdfDoc, new HashPrintRequestAttributeSet());
fis.close();

If you don't want to use a FileInputStream, you can always create the PDF as a ByteArrayOutputStream and use the resulting byte[] to create a ByteArrayInputStream.

That's what the practical answer is about: it's not that difficult to create a PDF in memory. That's done like this:

ByteArrayOutputStream baos = new ByteArrayOutputStream();
Document document = new Document();
PdfWriter.getInstance(document, baos);
document.open();
// add content
document.close();
byte[] pdf = baos.toByteArray();

The question is: what are you going to do with pdf?

Either your printer understands those bytes (there are printers that accept PDF syntax), or you'll have to find software that converts PDF into a format that printers understand. Usually, people use PDF rendering software (such as Adobe Reader) to print a document. Many of these viewers (Adobe Reader is one of them), require the file to exist as a file: Adobe Reader does not accept a byte array.

This explains why the practical answer isn't as easy as the theoretical answer: in practice, your question is far from trivial: it depends on the printer (which formats does it accept) and the PDF viewer (should you require one).

Solution 2

Try this :

filename = "aaaaaaa.pdf";
java.io.File fileout =  new File(filename);
com.lowagie.tools.Executable.printDocumentSilent(fileout));
 fileout.delete();  // if you don't want to keep it.    
Share:
20,416
fareed
Author by

fareed

coder, builder, maker, for the past 10 years

Updated on January 09, 2022

Comments

  • fareed
    fareed over 2 years

    I am using iText to generate a pdf and write it to the file system as the following:

    private void createPDF() throws Exception{
        com.itextpdf.text.Document doc = new com.itextpdf.text.Document();
        PdfWriter docWriter = null;
        path = "C:\\PATH\\TO\\Desktop\\EXAMPLE_FOLDER\\" + pdfFilename;
        docWriter = PdfWriter.getInstance(doc, new FileOutputStream(path));
        doc.addTitle("Invoice");
        doc.setPageSize(PageSize.A4);
        doc.open();
        PdfContentByte cb = docWriter.getDirectContent();
        fillPDFDetails(cb);
        if (doc != null) {
            doc.close();
        }
        if (docWriter != null) {
            docWriter.close();
        }
    }
    

    However, I want to send the pdf to the printer and print the pdf file instead of writing it to the file system. How can I achieve this?

  • fareed
    fareed about 9 years
    I have implemented your code, I'm getting the java.io.IOException: The document has no pages Exception.
  • Bruno Lowagie
    Bruno Lowagie about 9 years
    That's because you didn't add anything where it says // add content.
  • fareed
    fareed about 9 years
    I'm adding the details there!
  • Bruno Lowagie
    Bruno Lowagie about 9 years
    The exception tells me that you aren't adding anything to the Document instance. So whatever the details are, it's not content.
  • fareed
    fareed about 9 years
    I used the same code to write the file into the file system and it was working properly. Can you please see the complete code here? codeshare.io/tFXNL
  • Bruno Lowagie
    Bruno Lowagie about 9 years
    Well, the exception is clear: it is only thrown if you're not adding any actual content.
  • fareed
    fareed about 9 years
    I have researched and found that adding document.add(new Chunk("")); will solve the problem. Then after that nothing happens! How would I know that the job was sent to the printer? Nothing appears and even windows print dialog is not appearing
  • Bruno Lowagie
    Bruno Lowagie about 9 years
    The process sets an internal flag that can be tested via the checkError method. My bet is that the printer doesn't accept PDF.
  • fareed
    fareed about 9 years
    But I can print any pdf file successfully with the connected printer! It appears that the printing job is not invoked
  • Bruno Lowagie
    Bruno Lowagie about 9 years
    Maybe you can print any PDF successfully from an application such as Adobe Reader, but that doesn't mean you can print that PDF from Java!
  • fareed
    fareed about 9 years
    Thank you for your answer! So based on your answer, it is not possible to print a pdf file from Java memory because this would mean that a pdf processor such as Adobe Reader would need to access Java memory which is impossible. Correct me if I'm wrong.
  • Bruno Lowagie
    Bruno Lowagie about 9 years
    You are wrong. If your printer understands PDF, you can print directly to a printer (but many printers don't understand PDF). It may be possible with a PDF rendering library such as idrsolutions.com/pdf-print-quick-start (you'd have to ask the people of IDR Solutions of JPedal accepts a byte[] instead of a path to a PDF file).
  • fareed
    fareed about 9 years
    I see. I think I need to find a better way of doing it then! Thanks anyways! I will accept your answer
  • Sibi John
    Sibi John over 6 years
    @fareed did you find a way? i also need to print an in memory pdf
  • fareed
    fareed over 6 years
    @SibiJohn yes, you can send the pdf to the printing service and it will print.
  • Sibi John
    Sibi John over 6 years
    @fareed in my case the printer is not able to understand the PDF byte syntax. i was hoping you had found a workaround.