在网上找了不少通过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...