【项目管理】Java使用pdfbox调用打印机打印PDF文件

news2024/11/18 17:54:25

【项目管理】Java使用pdfbox调用打印机打印PDF文件

  • 1.项目前言
  • 2.项目实现
  • 3.关键代码
  • 4.效果演示
  • 5.问题处理
    • 5.1 安装对应字体
    • 5.2 修改对应代码

系统:Win10
Java:1.8.0_333
IDEA:2020.3.4
Gitee:https://gitee.com/lijinjiang01/Printer

1.项目前言

在工作中,有次收到一位同事给我提的建议,说公司的CS系统,能不能直接调用打印机打印PDF,因为我们的系统之前是将表单导出PDF到本地,然后再打开打印,而他的工作有很大一部分是需要打印表单的,所以为了减轻工作量,向我提了这份需求申请,我先考虑了一下这个需求的实现难度,感觉应该是可以实现的,就答应了下来。

2.项目实现

为了实现这个功能,我先去网上查找了一下资料,对比了一下实现难度以及我们当前所处的环境(因为我们公司文件落地加密,所以直接调用打印机打印是不好实现的),我最终选择使用 Apache PDFbox 这个开源项目来实现 PDF 文件格式的打印。

Apache PDFbox 是一个开源的、基于 Java 的、支持 PDF 文档生成的工具库,它可以用于创建新的 PDF 文档,修改现有的 PDF 文档,还可以从 PDF 文档中提取所需的内容。Apache PDFBox 还包含了数个命令行工具。可以说,这个开源的工具库的功能是很强大的,在此,我们只研究打印功能。

Apache PDFbox 的优点:功能强大,代码开源,较完美的解决了 PDF 格式文件的一系列处理,使用方便。

3.关键代码

这里我们获取了本地的所有打印机服务,并将系统的默认打印机作为首选项

//获取本地的打印服务,并且设置默认打印机
private JComboBox<String> selectPrintService() {
    defaultPrintService = PrintServiceLookup.lookupDefaultPrintService();//获取默认打印机
    JComboBox<String> comboBox = new JComboBox<>();
    //获得本台电脑连接的所有打印机
    PrintService[] printServices = PrinterJob.lookupPrintServices();
    if (printServices == null || printServices.length == 0) {
        comboBox.addItem("获取本地打印机失败,请联系管理员!");
    } else {
        for (PrintService printService : printServices) {
            String value = printService.getName();
            serviceMap.put(value, printService);//将打印机名称及打印机服务添加到集合
            comboBox.addItem(value);
            //将默认打印机设置为下拉选的默认选择项
            if (defaultPrintService != null && defaultPrintService.getName().equals(value)) {
                comboBox.setSelectedItem(value);
            }
        }
    }
    return comboBox;
}
//打印功能实现
public void print(Container parent) {
    PDDocument document = null;
    File file;
    try {
        file = new File(filepath);
        if (file == null || !file.exists()) {
            JOptionPane.showMessageDialog(parent, "要打印的PDF文件不存在!", "警告", JOptionPane.WARNING_MESSAGE);
            return;
        }
        document = PDDocument.load(file);
        PrinterJob printerJob = PrinterJob.getPrinterJob();
        printerJob.setJobName(file.getName());
        printerJob.setPrintService(defaultPrintService);//设置打印机
        //设置纸张及缩放
        PDFPrintable pdfPrintable = new PDFPrintable(document, scaling);
        //设置多页打印
        Book book = new Book();
        PageFormat pageFormat = new PageFormat();
        //设置打印方向
        pageFormat.setOrientation(orientation);//纵向
        Paper paper = getPaper();
        pageFormat.setPaper(paper);
        book.append(pdfPrintable, pageFormat, document.getNumberOfPages());
        printerJob.setPageable(book);
        printerJob.setCopies(copies);//设置打印份数
        //添加打印属性
        HashPrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet();
        attributes.add(sides); //设置单双页
        attributes.add(MediaSizeName.ISO_A4);//默认A4纸打印
        printerJob.print(attributes);

    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (document != null) {
            try {
                document.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

private Paper getPaper() {
    Paper paper = new Paper();
    // 默认为A4纸张,对应像素宽和高分别为 595, 842
    int width = 595;
    int height = 842;
    // 设置边距,单位是像素,10mm边距,对应 28px
    int marginLeft = 12;
    int marginRight = 12;
    int marginTop = 12;
    int marginBottom = 12;
    paper.setSize(width, height);
    // 下面一行代码,解决了打印内容为空的问题
    paper.setImageableArea(marginLeft, marginRight, width - (marginLeft + marginRight), height - (marginTop + marginBottom));
    return paper;
}

4.效果演示

运行之后,会弹出类似这个的界面,简单配置下(这里的参数都是默认的,一般用这些就可以直接打印),点击打印,就会将文件传送到打印机服务的打印队列进行打印
在这里插入图片描述
我这里选择了 Microsoft Print to PDF 测试一下
在这里插入图片描述
这里我们发现使用pdfbox打印出来的PDF的字体发生了改变,打印的结果和原PDF不一致
在这里插入图片描述

5.问题处理

这里我们去控制台看一下为什么会出现这个问题,在这里我们不难发现导致这个问题的原因在于:原PDF中用到了一种 STSong-Light 的字体,而我们系统没有安装这个字体,所以他就自动给我们换了一个字体,难怪变得这么丑了,这里我们给出两种解决办法
在这里插入图片描述

5.1 安装对应字体

因为程序检测到我们没有安装这种字体,我们只需要将对应字体安装上去,然后重启电脑,应该就能解决这个问题

5.2 修改对应代码

因为我们不可能给每个用户加装一个字体,所以我们只能从程序出发

我们去交友网站上找到该项目的源码地址:https://github.com/apache/pdfbox/tree/trunk/pdfbox,本来想用源码的,不过可能版本不同,会报错。

所以我们可以在 pdfbox 的 org.apache.pdfbox.pdmodel.font 路径下找到 FontMapperImpl.class 文件,然后把他的反编译代码复制到我们项目中(记得先创建路径文件夹)
然后在字体映射集合中添加所缺字体的映射字体(映射的字体选择系统中有的,且和所缺字体近似的字体)就可以了

//添加STSong-Light字体映射
this.substitutes.put("STSong-Light", Arrays.asList("STSong-Light", "SimSun", "SIMFANG", "STFangsong"));

在这里插入图片描述
然后再重试下,就发现可以正常打印了
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/29757.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何使用轮播图实现水平内容自动切换

通过轮播图实现一个水平内容自动切换 效果展示 前置准备 三张背景图片 具体步骤 添加一个轮播图组件 添加一个图片 添加一个标题 添加数据表 添加事件 添加触发器 绑定数据 步骤拆解 添加一个轮播图组件 1.1 拖拽 轮播图 到 编辑区 1.2 调整 轮播图 样式 添加一个图片 …

有关QT的问题大全

文章目录现在2022年&#xff0c;Qt发展如何&#xff1f;是就业的好选择吗&#xff1f;如何学习Qt,c到什么程度可以去学qt&#xff1f;现在 Qt 好找工作吗&#xff1f;为什么工业软件开发一般用的都是QT&#xff1f;初学QT怎么学?请问目前做windows桌面应用程序&#xff0c;MFC…

工作中Java Stream的简单应用

标题开发使用filter() and map()max()根据集合对象中的某个属性取最大值先解释一下各变量含义: temps集合是userids的子集(大前提) cache是temps集合在userids集合中的补集 简单来说就是,userids集合-temps集合cache补集,如下图所示目标:此次为工作中实际遇到的问题,需要得到c…

C++编译链接

文章目录C编译链接C编译模式分离式编译是个啥&#xff1f;怎么实现上述过程&#xff1f;定义与声明引出新的问题头文件有关头文件用来干啥&#xff1f;include头文件中应该写什么&#xff1f;#ifndef通过gcc/g命令来看完整的编译链接过程预处理(Preprocessing)编译(Compilation…

院内导航系统哪家口碑好?医疗院内导航地图公司排名

“医生&#xff0c;请问验血怎么走&#xff1f;”   “护士&#xff0c;请问药房在哪儿&#xff1f;”   “您好&#xff0c;做CT在什么地方&#xff1f;”   这些问题是医生和护士经常遇到的问题。的确&#xff0c;患者就诊时&#xff0c;由于对医院环境不熟悉&#xff…

云计算(虚拟化)面试宝典

一:服务器虚拟化 1.名词解释 (1)资源动态调整(对象是虚拟机) 管理员操作,对CPU、内存、网卡、硬盘、GPU进行调整。 FusionCompute支持虚拟机资源动态调整,用户可以根据业务负载动态调整资源的使用情况。 虚拟机资源调整包括: 离线/在线调整vCPU数目 无论虚拟机处于离线…

如何使用C++图形界面开发框架Qt创建一个应用程序?(Part 3)

Qt是目前最先进、最完整的跨平台C开发工具。它不仅完全实现了一次编写&#xff0c;所有平台无差别运行&#xff0c;更提供了几乎所有开发过程中需要用到的工具。如今&#xff0c;Qt已被运用于超过70个行业、数千家企业&#xff0c;支持数百万设备及应用。 点击获取Qt组件下载 …

Flink的状态编程

Flink 处理机制的核心&#xff0c;就是“有状态的流式计算”。在流处理中&#xff0c;数据是连续不断到来和处理的。每个任务进行计算处理时&#xff0c;可以基于当前数据直接转换得到输出结果&#xff1b;也可以依赖一些其他数据。这些由一个任务维护&#xff0c;并且用来计算…

【HAL库】STM32CubeMX开发----STM32F407----CAN通信实验

STM32CubeMX 下载和安装 详细教程 【HAL库】STM32CubeMX开发----STM32F407----目录 前言 本次实验以 STM32F407VET6 芯片为MCU&#xff0c;使用 25MHz 外部时钟源。 CAN通信波特率为 500K bps。 CAN通信引脚 与 MCU引脚 对应关系如下&#xff1a; CAN通信引脚MCU引脚TXPB9RXP…

虹科教您 | 虹科Automation softPLC入门操作指南(2)——子程序和用户自定义功能块 UDFB

虹科KPA Automation softPLC是为Linux、Xenomai、INtime、Windows等实时操作系统开发PLC的编程环境&#xff0c;适合需要使用IEC61131-3和PLCopen标准的控制技术和进行PLC编程的用户。本篇文章将帮助您创建和使用IEC语言开发的函数和功能块。 Automation softPLC Studio 命名规…

kettle 9.2源码打包和idea环境启动及常见错误

一&#xff1a;源码打包 这里为什么是kettle 9.2&#xff0c;因为kettle 9.3需要jdk11 这里直接去下载kettle的源码&#xff0c;tag9.2.0.4-R。这里需要自己搭建一个nexus仓库&#xff0c;因为有些包从kettle的仓库里面下载不下来。 nexus新建仓库代理, 记得加到public里面去 …

学术界or工业界,高校博后转行大厂工程师心得!

8本电子书免费送给大家&#xff0c;见文末。 导读&#xff1a;以下是这篇文章是一位 七月在线 学员的的学习和面试经历的分享&#xff0c;现将学员学习和面试心得分享给大家&#xff0c;祝大家都能有好的offer。 1 个人情况 我之前在高校做博后&#xff0c;现在转行到大厂做…

数据库的基本操作(7)

在这一篇博客中我将对数据库进行一个结尾&#xff0c;这将是关于数据库基本内容的结尾。 首先我们来简单总结一下前面的内容&#xff1a; 前面主要讲了Mysql中的索引和事务&#xff0c;这是面试必考的内容。 索引&#xff0c;怎么理解索引呢&#xff1f; 1.索引存在的意义&…

通用汽车在华加速推出智能电动车型

到2025年底前&#xff0c;推出超过15款基于奥特能平台打造的电动车型基于奥特能平台的雪佛兰FNR-XE纯电概念车全球首发通用汽车全新“软件定义汽车”平台将于明年正式推出近日&#xff0c;通用汽车中国在上海举办了“2022科技展望日”&#xff0c;展示了其在Ultium奥特能全球电…

IE高级配置中支持的SSL/TLS协议对应注册表值

一、手动勾选"Internet选项->高级->安全->使用TLS 1.2" 二、以编程方式勾选"Internet选项->高级->安全->使用TLS 1.2" 1.注册表值SecureProtocols对应的含义 注册表的路径为&#xff1a;HKEY_CURRENT_USER\Software\Microsoft\Windows…

【第六部分 | JavaScript高级】2:函数高级

目录 【第二章】函数进阶 | &#xff08;复习&#xff09;函数声明 | 函数也是对象 | 函数的this指向 | 改变函数this的指向 | 函数的“严格模式” | 闭包 | 浅拷贝和深拷贝 【第二章】函数进阶 | &#xff08;复习&#xff09;函数声明 | 函数也是对象 Java中的方法好…

Android基础二:常见的几种组件

关注我&#xff0c;会持续发布关于Android学习的内容&#xff01; 文章目录 前言 一、MaterialButton 二、MaterialButtonToggleGroup 三、TextView 文本组件 四、ImageView控件 总结 前言 本节我们来学习安卓&#xff08;Android&#xff09;的几种常用的组件&#xff0c;包括…

PTA题目 装睡

你永远叫不醒一个装睡的人 —— 但是通过分析一个人的呼吸频率和脉搏&#xff0c;你可以发现谁在装睡&#xff01;医生告诉我们&#xff0c;正常人睡眠时的呼吸频率是每分钟15-20次&#xff0c;脉搏是每分钟50-70次。下面给定一系列人的呼吸频率与脉搏&#xff0c;请你找出他们…

VMware虚拟机安装ubuntu-16.04.5详细教程

不是每一位程序员都必须玩过linux&#xff0c;现在大多数服务器都是linux系统的&#xff0c;很多生产上的框架和工具都是安装在服务器上的&#xff0c;而且有不少大公司都要求熟悉在linux上开发&#xff0c;因此小编个人觉得大家有必要去了解一下linux&#xff08;现在大部分服…

vue.js毕业设计,基于vue.js前后端分离图书购物商城系统设计与实现(H5移动项目)

功能介绍 【后台管理员功能】 会员列表&#xff1a;查看所有注册会员信息&#xff0c;支持删除 录入资讯&#xff1a;录入资讯标题、内容等信息 管理资讯&#xff1a;查看已录入资讯列表&#xff0c;支持删除和修改 广告设置&#xff1a;上传图片和设置小程序首页轮播图广告地…