在网上找了不少通过jdk的printService服务打印pdf的博客,都大同小异,打印调用了但是没有真的打印,最后终于找到一个可用的,这里记录一下。

首先通过maven引入依赖:

        <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>pdfbox</artifactId>
            <version>2.0.6</version>
        </dependency>

最后使用工具类:

package com.ruoyi.mrs.utils;
import com.itextpdf.text.Document;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfWriter;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.StringUtils;
import org.apache.commons.io.IOUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.printing.PDFPrintable;
import org.apache.pdfbox.printing.Scaling;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.Copies;
import javax.print.attribute.standard.MediaSizeName;
import javax.print.attribute.standard.Sides;
import java.awt.print.Book;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.PrinterJob;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
 * @author fmi110
 * @description 打印工具类
 * @date 2021/11/16 14:22
public class PrintUtil {
    private static final Logger log = LoggerFactory.getLogger(PrintUtil.class);
     * 寻找指定的打印机
     * @param printerName
     * @return
    public static PrintService lookupPrinter(String printerName) {
        PrintService service = null;
        PrintService[] printServices = PrintServiceLookup.lookupPrintServices(null, null);
        if (printServices == null || printServices.length == 0) {
            throw new BusinessException("未获取到打印服务");
        List<String> printerNames = Arrays.stream(printServices).map(p -> p.getName()).collect(Collectors.toList());
        log.info(">>>>可选的打印机:{}", printerNames);
        for (int i = 0; i < printServices.length; i++) {
            String name = printServices[i].getName().toLowerCase();
            log.info("printName{}:{}", i, name);
            if (name.contains(printerName.toLowerCase())) {
                service = printServices[i];
                break;
        if (service == null) {
            throw new BusinessException("未找到指定的打印机:" + printerName + ",可选打印服务:" + printerNames);
        return service;
    public static void print(String filePath, String printerName, PrintRequestAttributeSet aset) throws Exception {
        print(new File(filePath), printerName, aset);
     * 打印指定文件
     * @param file
     * @param printerName
     * @param aset 打印属性,可通过这个设置打印份数
     * @throws Exception
    public static void print(File file, String printerName, PrintRequestAttributeSet aset) throws Exception {
        if (file == null) {
            log.error("传入的文件为空");
            throw new Exception("传入的文件为空");
        if (!file.exists()) {
            log.error("文件不存在:" + file.getAbsolutePath());
            throw new Exception("文件不存在:" + file.getAbsolutePath());
        PrintService printService = lookupPrinter(printerName);
        if (null == aset) {
            aset = getPrintRequestAttributeSet(); // 获取打印参数
        PDDocument document = PDDocument.load(file);
        PrinterJob printJob = PrinterJob.getPrinterJob();
        printJob.setJobName(file.getName());
        printJob.setPrintService(printService); // 选择打印机
        //设置纸张及缩放
        PDFPrintable pdfPrintable = new PDFPrintable(document, Scaling.ACTUAL_SIZE);
        //设置多页打印
        Book book = new Book();
        PageFormat pageFormat = new PageFormat();
        //设置打印方向
        pageFormat.setOrientation(PageFormat.PORTRAIT);//纵向
        pageFormat.setPaper(getPaper());//设置纸张
        book.append(pdfPrintable, pageFormat, document.getNumberOfPages());
        printJob.setPageable(book);
        try {
            printJob.print(aset);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("打印机打印异常:{}", e.getMessage());
            throw new Exception("打印机打印异常:" + e.getMessage());
        } finally {
            IOUtils.closeQuietly(document);
    private static PrintRequestAttributeSet getPrintRequestAttributeSet() {
        PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
        aset.add(new Copies(1)); //份数
        aset.add(MediaSizeName.ISO_A4); //纸张
        // aset.add(Finishings.STAPLE);//装订
        aset.add(Sides.ONE_SIDED);//单双面
        return aset;
     * 设置打印份数
     * @param copy
     * @return
    public static PrintRequestAttributeSet getPrintRequestAttributeSet(int copy) {
        PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
        aset.add(new Copies(copy)); //份数
        aset.add(MediaSizeName.ISO_A4); //纸张
        // aset.add(Finishings.STAPLE);//装订
        aset.add(Sides.ONE_SIDED);//单双面
        return aset;
     * 将图片转换成pdf
     * @return
     * @throws Exception
    public static byte[] img2PDF(List<byte[]> images) throws Exception {
        Document doc = new Document(PageSize.A4, 0, 0, 36.0F, 36.0F);//普通a4
        ByteArrayOutputStream pdfOut = new ByteArrayOutputStream();
        PdfWriter.getInstance(doc, pdfOut);
        doc.open();
        for (byte[] image : images) {
            com.itextpdf.text.Image pic = com.itextpdf.text.Image.getInstance(image);
            pic.setScaleToFitLineWhenOverflow(true);
            doc.add(pic);
        doc.close();
        byte[] pdf = pdfOut.toByteArray();
        IOUtils.closeQuietly(pdfOut);
        return pdf;
     * 图片缩放成A4尺寸,转换为pdf文件
     * @param imagePath
     * @param descfolder
     * @return
     * @throws Exception
    public static String img2PDF(String imagePath, String descfolder, String pdfName) {
        return img2PDF(Arrays.asList(imagePath), descfolder, pdfName);
     * 图片缩放成A4尺寸,转换为pdf文件
     * @param imgPaths
     * @param descfolder
     * @return
     * @throws Exception
    public static String img2PDF(List<String> imgPaths, String descfolder) {
        String pdfName = System.currentTimeMillis() + ".pdf";
        return img2PDF(imgPaths, descfolder, pdfName);
    public static String img2PDF(List<String> imgPaths, String descfolder, String pdfName) {
        pdfName = StringUtils.isEmpty(pdfName) ? System.currentTimeMillis() + ".pdf" : pdfName;
        String pdfPath = "";
        FileOutputStream fos = null;
        try {
            File file = new File(descfolder);
            if (!file.exists()) {
                file.mkdirs();
            pdfPath = descfolder + "/" + pdfName;
            Document doc = new Document(PageSize.A4, 0, 0, 0, 0);
            fos = new FileOutputStream(pdfPath);
            PdfWriter.getInstance(doc, fos);
            doc.open();
            for (String imagePath : imgPaths) {
                com.itextpdf.text.Image image = image = com.itextpdf.text.Image.getInstance(imagePath);
                image.scaleAbsolute(PageSize.A4.getWidth(), PageSize.A4.getHeight());
                doc.add(image);
            doc.close();
            log.info("生成pdf成功:{}", pdfPath);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("生成pdf异常:" + e.getMessage());
            throw new BusinessException("生成pdf异常:" + e.getMessage());
        } finally {
            IOUtils.closeQuietly(fos);
        return pdfPath;
    public static void main(String[] args) throws Exception {
        File file = new File("D:\\test\\2.pdf");
        print(file, "HP Las", getPrintRequestAttributeSet(1));
//        PDDocument document =  PDDocument.load(file);
//        PrinterJob printJob = PrinterJob.getPrinterJob();
//        printJob.setJobName(file.getName());
//        PrintService printService = lookupPrinter("HP Las");
//        printJob.setPrintService(printService);
//        //设置纸张及缩放
//        PDFPrintable pdfPrintable = new PDFPrintable(document, Scaling.ACTUAL_SIZE);
//        //设置多页打印
//        Book book = new Book();
//        PageFormat pageFormat = new PageFormat();
//        //设置打印方向
//        pageFormat.setOrientation(PageFormat.PORTRAIT);//纵向
//        pageFormat.setPaper(getPaper());//设置纸张
//        book.append(pdfPrintable, pageFormat, document.getNumberOfPages());
//        printJob.setPageable(book);
//        printJob.setCopies(1);//设置打印份数
//        //添加打印属性
//        HashPrintRequestAttributeSet pars = new HashPrintRequestAttributeSet();
//        pars.add(Sides.ONE_SIDED); //设置单双页
//        printJob.print(pars);
    public static Paper getPaper() {
        Paper paper = new Paper();
        // 默认为A4纸张,对应像素宽和高分别为 595, 842
        int width = 595;
        int height = 842;
        // 设置边距,单位是像素,10mm边距,对应 28px
        int marginLeft = 10;
        int marginRight = 0;
        int marginTop = 10;
        int marginBottom = 0;
        paper.setSize(width, height);
        // 下面一行代码,解决了打印内容为空的问题
        paper.setImageableArea(marginLeft, marginRight, width - (marginLeft + marginRight), height - (marginTop + marginBottom));
        return paper;

 通过main函数可测试结果。

水晶报表rpt转pdf SAP提供的SDK在 windows下正常, 但在linux下的tomcat里报错 Caused by: com.crystaldecisions.sdk.occa.report.lib.ReportSDKException: javax.print.PrintServiceLookup: Provider sun.print.Win32PrintServiceLookup not found Caused by: com.crystaldecisions.sdk.occa.repo
一、Java打印简介 在我们的实际工作中,经常需要实现打印功能。但由于历史原因,Java 提供的打印功能一直都比较弱。实际上最初的 jdk 根本不支持打印,直到 jdk1.1 才引入了很轻量的打印支持。实际上,SUN 公司也一直致力于 Java 打印功能的完善,而 Java2 平台则终于有了一个健壮的打印模式的开端, jdk1.4 则提供了一套完整的"Java 打印服务 API" (Java Print Service API),它对已有的打印功能是积极的补充。 1、DocPrintJobHandler --已经执行 打印JPG图片格式的文件,本次采用的Java原生的打印方式。 优点:jdk的原生支持的打印功能,可直接使用,支持设置各项打印参数。 缺点:局限性较大,只能打印一些图片和文本格式的文 package com.my.print.handler; import org.springframework.util.StringUtils; import javax.print.*; import javax
接口 PrintService 是 DocPrintJob 的工厂。PrintService 描述了打印机的功能,并可查询它来了解打印机支持的属性。 Java代码 importjava.io.File; importjava.io.FileInputStream; importjavax.print.Doc; importja...