Print a PDF Document in Java

For some time now I have searched for a way to print a PDF document from Java code. Up to now, I have had to shell out and invoke Acrobat from the command line but this hack has been painful to support in the field because of the multiple version of Acrobat and its quirks.

A new PDF Renderer project has recently been released on java.net which can in addition to rendering and viewing a PDF document, it can be used to print a PDF document. If you download the PDF Renderer you can run the jar to start a sample PDF viewer application which can print PDF documents. All the code listed below is inspired from the PDF Renderer sample application.

The following code uses classes from the PDF Renderer library and standard Java. Like usual, I have omitted all import statements.

// Create a PDFFile from a File reference
File f = new File("c:\\juixe\\techknow.pdf");
FileInputStream fis = new FileInputStream(f);
FileChannel fc = fis.getChannel();
ByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
PDFFile pdfFile = new PDFFile(bb); // Create PDF Print Page
PDFPrintPage pages = new PDFPrintPage(pdfFile);

// Create Print Job
PrinterJob pjob = PrinterJob.getPrinterJob();
PageFormat pf = PrinterJob.getPrinterJob().defaultPage();
pjob.setJobName(f.getName());
Book book = new Book();
book.append(pages, pf, pdfFile.getNumPages());
pjob.setPageable(book);

// Send print job to default printer
pjob.print();

One critical class required to print a PDF document using PDF Renderer is the PDFPrintPage. The PDFPrintPage implements the Printable print method. The PDFPrintPage is included in the PDFRenderer.jar, but in the source distribution it is found under the demos project. I have included the source to PDFPrintPage print method here…

class PDFPrintPage implements Printable {
  private PDFFile file;
  PDFPrintPage(PDFFile file) {
    this.file = file;
  }

  public int print(Graphics g, PageFormat format, int index) 
    throws PrinterException {
    int pagenum = index + 1;

    // don't bother if the page number is out of range.
    if ((pagenum >= 1) && (pagenum < = file.getNumPages())) {
      // fit the PDFPage into the printing area
      Graphics2D g2 = (Graphics2D)g;
      PDFPage page = file.getPage(pagenum);
      double pwidth = format.getImageableWidth();
      double pheight = format.getImageableHeight();

      double aspect = page.getAspectRatio();
      double paperaspect = pwidth / pheight;

      Rectangle imgbounds;

      if (aspect>paperaspect) {
        // paper is too tall / pdfpage is too wide
        int height= (int)(pwidth / aspect);
        imgbounds= new Rectangle(
          (int)format.getImageableX(),
          (int)(format.getImageableY() + ((pheight - height) / 2)),
          (int)pwidth,
          height
        );
      } else {
        // paper is too wide / pdfpage is too tall
        int width = (int)(pheight * aspect);
        imgbounds = new Rectangle(
          (int)(format.getImageableX() + ((pwidth - width) / 2)),
          (int)format.getImageableY(),
          width,
          (int)pheight
        );
      }

      // render the page
      PDFRenderer pgs = new PDFRenderer(page, g2, imgbounds, null, null);
      try {
        page.waitForFinish();
        pgs.run();
      } catch (InterruptedException ie) {}

      return PAGE_EXISTS;
    } else {
      return NO_SUCH_PAGE;
    }
  }
}

A final note, PDF Renderer does require Java 1.5 or greater.

Related posts:

  1. Word To PDF
  2. How To Print The Alphabet in Java?
  3. Rails PDF Plugin
  4. Print HTML Using IE
  5. Windows Print Screen Key
  6. Java.class


62 Responses to “Print a PDF Document in Java”

  • james Says:

    This is what i use to keep the original pdf size :

    	/* fit the PDFPage into the printing area */
    	Graphics2D a_o_graphic = (Graphics2D)the_o_graphics;
    	PDFPage a_o_page = my_o_file.getPage(a_i_pagenum);
    
    	double pwidth = the_o_format.getImageableWidth();
    	double pheight = the_o_format.getImageableHeight();
     
    	Rectangle a_o_imageArea;
     
        if (pwidth >= a_o_page.getWidth() || pheight >= a_o_page.getHeight()) {
    	/* Define the image area */
    		a_o_imageArea = new Rectangle((int) the_o_format.getImageableX(), (int) the_o_format.getImageableY(),
    		(int) a_o_page.getWidth(), (int) a_o_page.getHeight());
    		a_o_graphic.translate(0, 0);
        }
        else{
    	/* Define the image area */
    		a_o_imageArea = new Rectangle((int) the_o_format.getImageableX(), (int) the_o_format.getImageableY(),
    		(int) the_o_format.getImageableWidth(), (int) the_o_format.getImageableHeight());
    		a_o_graphic.translate(0, 0);
        }
    

    I hope it can be useful for someone :)

  • Bainer Says:

    Thank you Barrett for figuring this thing out!!

  • Stampare PDF da Java | Lady Blackice Says:

    [...] che facevano al caso mio! Prima parte: per mandare in stampa il PDF ho seguito le istruzioni di questo post, che suggerisce l’utilizzo della libreria PDF Renderer. Solo una correzione al codice [...]

  • Print & PDF Document in Java | P3r3s' Notes Says:

    [...] Print a PDF Document in Java. This entry was posted in Code and tagged java by abrioso. Bookmark the permalink. [...]

  • Clement Says:

    Very nice code, very simple and useful.
    Thank you.

  • Jhay Says:

    How to use this through PHP where I can pass a variable that has the link to my PDF? For example, an external PDF or internal…

  • Techie Says:

    Hi Friends,

    Thanks for sharing this example.

    I am facing issue when I print on Linux/Unix machine.
    It is printing Binary (Junk Chars) not the actual PDF Doc.
    Same code is working fine on Windows.
    If any one of you know the solution or any inputs, highly appreciated.

    Thanks in Advance.

  • Shoaib Ahmed Says:

    this library is just superb… helped me a lot. i worked with it for the printinig purpose…

  • cisq Says:

    Great work, many thanks

  • windspy Says:

    thanks, it’s really helpful.

  • HoffiMuc Says:

    Here a working class for pdf print printing with javax.print in one class for DIN A4 honoring the PrintRequestAttributeSet:

    package scrapbook;
    
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Rectangle;
    import java.awt.print.PageFormat;
    import java.awt.print.Printable;
    import java.awt.print.PrinterException;
    import java.io.File;
    import java.io.FileInputStream;
    import java.nio.ByteBuffer;
    
    import javax.print.DocFlavor;
    import javax.print.DocPrintJob;
    import javax.print.PrintException;
    import javax.print.PrintService;
    import javax.print.PrintServiceLookup;
    import javax.print.SimpleDoc;
    import javax.print.attribute.HashPrintRequestAttributeSet;
    import javax.print.attribute.PrintRequestAttributeSet;
    import javax.print.attribute.standard.Copies;
    import javax.print.attribute.standard.MediaPrintableArea;
    import javax.print.attribute.standard.MediaTray;
    import javax.print.attribute.standard.OrientationRequested;
    import javax.print.attribute.standard.Sides;
    
    import com.sun.pdfview.PDFFile;
    import com.sun.pdfview.PDFPage;
    import com.sun.pdfview.PDFRenderer;
    
    import de.santix.sat.server.util.logging.LogHelper;
    
    /**
     * Printing of pdf with PDFRenderer.jar.
     * honors the given PrintRequestAttributeSet
     * 
     * @author hoffmann
     */
    public final class PdfRendererStandalonePrint
    {
        /** points per inch. */
        public static final float POINTS_PER_INCH = 72.0f;
        /** width in inch for an ISO_A4 paper. */
        public static final float A4_INCH_WIDTH = 8.27f;
        /** height in inch for an ISO_A4 paper. */
        public static final float A4_INCH_HEIGHT = 11.69f;
    
        /** hidden constructor. */
        private PdfRendererStandalonePrint()
        {};
    
        /**
         * args[0] absolute path of pdfFile.
         * args[1] printerName to print to
         * 
         * @param args
         *            call arguments
         */
        public static void main(String[] args) {
            try {
                File file = new File(args[0]);
                FileInputStream fis = new FileInputStream(file);
    
                byte[] pdfBytes = new byte[(int) file.length()];
                int bytesRead = fis.read(pdfBytes);
                if (bytesRead = 1) && (pagenum <= pdfFile.getNumPages())) {
                            Graphics2D g2 = (Graphics2D) graphics;
                            PDFPage page = pdfFile.getPage(pagenum);
    
                            // fit the PDFPage into the printing area
                            // Rectangle imageArea = new Rectangle((int) format.getImageableX(), (int) format.getImageableY(), (int)
                            // format.getImageableWidth(),
                            // (int) format.getImageableHeight());
                            // g2.translate(0, 0);
    
                            // no scaling, center PDF
                            Rectangle imageArea = new Rectangle(
                                    (int) (pageFormat.getImageableX() + pageFormat.getImageableWidth() / 2 - page.getWidth() / 2),
                                    (int) (pageFormat.getImageableY() + pageFormat.getImageableHeight() / 2 - page.getHeight() / 2),
                                    (int) page.getWidth(), (int) page.getHeight());
    
                            PDFRenderer pgs = new PDFRenderer(page, g2, imageArea, null, null);
                            try {
                                page.waitForFinish();
                                pgs.run();
                            } catch (InterruptedException ie) {
                                LogHelper.error("InterruptedException in PdfPrintPage.print()");
                                // nothing to do
                            }
                            return PAGE_EXISTS;
                        } else {
                            return NO_SUCH_PAGE;
                        }
                    }
                };
    
                javaxPrint(pages, args[1], file.getName()); // new javax.print
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * printing the PdfPrintPages with javax.print.
         * honors the given PrintRequestAttributeSet
         * 
         * @param pages
         *            PdfPrintPages which implements java.awt.Printable
         * @param printerName
         *            name of the printer
         * @param printJobName
         *            printjob name
         * @throws PrintException
         *             in case of an error
         */
        private static void javaxPrint(Printable pages, String printerName, String printJobName) throws PrintException {
            PrintService printService = getPrintService(printerName);
            DocPrintJob printJob = printService.createPrintJob();
            printJob.print(new SimpleDoc(pages, DocFlavor.SERVICE_FORMATTED.PRINTABLE, null), getPrintRequestAttributes());
        }
    
        /**
         * Lookup PrintService by printerName.
         * 
         * @param printerName
         *            printers Name
         * @return PrintService
         * @throws PrintException
         *             in case of an error
         */
        public static PrintService getPrintService(String printerName) throws PrintException {
            // args[1] = printerName (e.g. "\\CASH\Kopierer Farbe PS")
            PrintService[] allPrintServices = PrintServiceLookup.lookupPrintServices(null, null);
            for (PrintService printService : allPrintServices) {
                if (printService.getName().equalsIgnoreCase(printerName)) {
                    return printService;
                }
            }
            throw new PrintException("printer \"" + printerName + "\" not found!");
        }
    
        /**
         * construct the Attributes for an javax.print.PrintJob.
         * 
         * @return PrintRequestAttributeSet
         */
        public static PrintRequestAttributeSet getPrintRequestAttributes() {
            PrintRequestAttributeSet aSet = new HashPrintRequestAttributeSet();
            aSet.add(new Copies(1));
            aSet.add(OrientationRequested.PORTRAIT);
            // aSet.add(MediaSizeName.ISO_A4);
            aSet.add(new MediaPrintableArea(0.0f, 0.0f, A4_INCH_WIDTH, A4_INCH_HEIGHT, MediaPrintableArea.INCH));
            aSet.add(Sides.DUPLEX);
            aSet.add(MediaTray.MAIN);
    
            return aSet;
        }
    }
    
  • Rodrigo Says:

    Very usefull program. I need to delete the pdf file after print it but it seems to be caught by some stream. I tried closing FileInputStream and FileChannel objetcs after delete the File object but it does not work. Any idea?

    Thaks in advance

Leave a Reply