spring boot 实现pdf模板导出

实现背景:

在某些场景中,我们需要从数据库或其他来源获取的数据信息,动态的导出Pdf文件,如准考证的打印等。这时我们需要借助第三方依赖包—itextpdf 来实现此需求。

一、制作PDF模板

1、在Word内制作模板

因为PDF常用的软件不支持编辑,所以先用Word工具,如WPS或者Office新建一个空白Word文档,里面制作出自己想要的样式。

2、将Word转换成PDF形式

将设置好的Word文档转换成PDF形式,保存起来。

3、编辑PDF准备bia

用Adobe Acrobat DC 软件打开保存好的PDF模板文件,点击右下角的更多工具按钮

通过网盘分享的文件:Acrobat Pro DC2022(64bit).zip
链接: https://pan.baidu.com/s/1vaVsoRfUHnpil36Gy1zvuQ?pwd=Bxh1 提取码: Bxh1

Adobe Acrobat DC安装参考地址:https://blog.csdn.net/qq_44111805/article/details/1283533

 

 

 

以上参考网址:https://blog.csdn.net/L28298129/article/details/118732743?spm=1001.2014.3001.5506

 

下面新增linux支持:

Linux 字体环境配置​

二、Linux 字体环境配置​​

1. ​​安装字体依赖​​

确保系统已安装字体工具和中文支持:

# Ubuntu/Debian sudo apt-get install fontconfig xfonts-utils # CentOS/RHEL sudo yum install fontconfig mkfontscale

2. ​​部署字体文件​​

将 SIMSUN.TTC 复制到字体目录并生成索引:

sudo mkdir -p /usr/share/fonts/myapp sudo cp SIMSUN.TTC /usr/share/fonts/myapp/ sudo mkfontscale /usr/share/fonts/myapp sudo fc-cache -fv # 刷新字体缓存

3. ​​验证字体可用性​​

检查字体是否加载成功:

fc-list | grep "SimSun" # 应显示字体路径和版本信息
 

 代码服务层如下:

@Override
        public void exportPtf(HttpServletRequest request, HttpServletResponse response, String id)
                        throws Exception {

                LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
                SysEmployee employee = sysEmployeeService.getById(user.getId());
                String organizeName = "无锡伟达";
                if (employee != null && employee.getOrgId() != null) {
                        SysOrganize org = organizeService.getById(employee.getOrgId());
                        organizeName = org != null ? org.getOrganizeName() : "无锡伟达";
                }
                DetectionReportDto detectionReportDto = queryById(id);
                List<DetectionReportItemDto> items = detectionReportDto.getReportItems();
                String fjTag = "";
                if (items != null && items.size() > 1) {
                        fjTag = items.size() + "";
                }
                String fileName = "产品检验报告";
                String titleStr = "产品检验报告";

                // 模板存放地址
                String templateUrl = uploadpath + File.separator + "other" + File.separator;
                switch (detectionReportDto.getReportType()) {
                        case 4:// 过程检验
                                templateUrl = templateUrl + "detectionreportCP" + fjTag + ".pdf";
                                break;
                        case 2: // 产品检验
                                templateUrl = templateUrl + "detectionreportCP" + fjTag + ".pdf";
                                break;
                        case 1: // 原料检验
                                templateUrl = templateUrl + "detectionreportYL.pdf";
                                fileName = "原料检验报告";
                                titleStr = "原料检验报告";
                                break;
                        default:
                                templateUrl = templateUrl + "detectionreportCP" + fjTag + ".pdf";
                                break;
                }
                fileName = fileName + "[" + detectionReportDto.getReportNumber() + "]";

                // 设置响应头
                response.setCharacterEncoding("UTF-8");
                response.setContentType("Application/pdf");
                response.setHeader("Content-Disposition",
                                "attachment;fileName=" + templateUrl);
                OutputStream out = null;
                ByteArrayOutputStream bos = null;
                PdfStamper stamper = null;
                PdfReader reader = null;
                try {
                        // 保存到本地
                        // out = new FileOutputStream(fileName);
                        // 输出到浏览器端
                        out = response.getOutputStream();
                        // 读取PDF模板表单
                        reader = new PdfReader(templateUrl);
                        // 字节数组流,用来缓存文件流
                        bos = new ByteArrayOutputStream();
                        // 根据模板表单生成一个新的PDF
                        stamper = new PdfStamper(reader, bos);
                        // 获取新生成的PDF表单
                        AcroFields form = stamper.getAcroFields();
                        // 给表单生成中文字体,这里采用系统字体,不设置的话,中文显示会有问题
                        String osName = System.getProperty("os.name").toLowerCase();
                        if (osName.contains("win")) {
                                // Windows 路径(项目内字体文件)
                                BaseFont font = BaseFont.createFont("C:/WINDOWS/Fonts/SIMSUN.TTC,1",
                                                BaseFont.IDENTITY_H,
                                                BaseFont.EMBEDDED);
                                form.addSubstitutionFont(font);
                        } else {
                                // Linux 路径(推荐使用相对路径或资源目录)
                                BaseFont font = BaseFont.createFont("/usr/share/fonts/myapp/SIMSUN.TTC,1",
                                                BaseFont.IDENTITY_H,
                                                BaseFont.EMBEDDED);
                                form.addSubstitutionFont(font);
                        }

                        // 装配数据
                        Map<String, Object> data = new HashMap<>();
                        data.put("titleStr", organizeName + titleStr);
                        data.put("organizeName", organizeName);
                        data.put("goodsNameStr", "NO." + detectionReportDto.getReportNumber());
                        data.put("createTime", DateUtils.date2Str(detectionReportDto.getCreateTime(),
                                        DateUtils.date_sdf.get()));
                        data.put("goodsName", detectionReportDto.getGoodsName());
                        String productionTime = DateUtils.date2Str(detectionReportDto.getProductionStartTime(),
                                        DateUtils.date_sdf_wz.get()) + "至"
                                        + DateUtils.date2Str(detectionReportDto.getProductionEndTime(),
                                                        DateUtils.date_sdf_wz.get());
                        data.put("productionTime",
                                        productionTime.equals("null至null") ? " " : productionTime);
                        data.put("models",
                                        detectionReportDto.getModels() != null
                                                        ? String.join(",", detectionReportDto.getModels())
                                                        : "");
                        data.put("batches",
                                        detectionReportDto.getBatches() != null
                                                        ? String.join(",", detectionReportDto.getBatches())
                                                        : "");
                        data.put("batchCount",
                                        detectionReportDto.getBatchCount() + detectionReportDto.getMeasuringUnitName());
                        data.put("sampleCount", detectionReportDto.getSampleCount()
                                        + detectionReportDto.getMeasuringUnitName());
                        data.put("comprehensiveJudgment",
                                        detectionReportDto.getComprehensiveJudgment() == 1 ? "合格" : "不合格");
                        data.put("comprehensiveJudgmentCont", detectionReportDto.getComprehensiveJudgmentCont());
                        data.put("detectionDate", DateUtils.date2Str(detectionReportDto.getDetectionDate(),
                                        DateUtils.date_sdf.get()));
                        data.put("employeeName", detectionReportDto.getEmployeeName());
                        data.put("detectionStandardName", detectionReportDto.getDetectionStandardName());
                        data.put("organizeName", organizeName);
                        // 动态行
                        if (items != null && items.size() > 0) {// 动态列有点复杂,时间紧,先按不同模板来
                                if (items.size() == 1) {
                                        DetectionReportItemDto dto = items.get(0);
                                        data.put("fill_1", dto.getDetectionStandardItemName());
                                        data.put("fill_2", dto.getDetectionStandardItemRequire());
                                        data.put("fill_3", dto.getDetectionResult() == 1 ? "合格" : "不合格");
                                        data.put("fill_3", dto.getDetectionConclusion());
                                }
                                if (items.size() == 2) {
                                        DetectionReportItemDto dto = items.get(0);
                                        data.put("fill_1", dto.getDetectionStandardItemName());
                                        data.put("fill_2", dto.getDetectionStandardItemRequire());
                                        data.put("fill_3", dto.getDetectionResult() == 1 ? "合格" : "不合格");
                                        data.put("fill_3", dto.getDetectionConclusion());
                                        DetectionReportItemDto dto2 = items.get(1);
                                        data.put("fill_11", dto2.getDetectionStandardItemName());
                                        data.put("fill_21", dto2.getDetectionStandardItemRequire());
                                        data.put("fill_31", dto2.getDetectionResult() == 1 ? "合格" : "不合格");
                                        data.put("fill_31", dto2.getDetectionConclusion());
                                }
                                if (items.size() == 3) {
                                        DetectionReportItemDto dto = items.get(0);
                                        data.put("fill_1", dto.getDetectionStandardItemName());
                                        data.put("fill_2", dto.getDetectionStandardItemRequire());
                                        data.put("fill_3", dto.getDetectionResult() == 1 ? "合格" : "不合格");
                                        data.put("fill_3", dto.getDetectionConclusion());
                                        DetectionReportItemDto dto2 = items.get(1);
                                        data.put("fill_11", dto2.getDetectionStandardItemName());
                                        data.put("fill_21", dto2.getDetectionStandardItemRequire());
                                        data.put("fill_31", dto2.getDetectionResult() == 1 ? "合格" : "不合格");
                                        data.put("fill_31", dto2.getDetectionConclusion());
                                        DetectionReportItemDto dto3 = items.get(2);
                                        data.put("fill_12", dto3.getDetectionStandardItemName());
                                        data.put("fill_22", dto3.getDetectionStandardItemRequire());
                                        data.put("fill_32", dto3.getDetectionResult() == 1 ? "合格" : "不合格");
                                        data.put("fill_32", dto3.getDetectionConclusion());
                                }
                        }
                        // 遍历data,给pdf表单赋值
                        for (String key : data.keySet()) {
                                form.setField(key, data.get(key).toString());
                        }
                        // 表明该PDF不可修改
                        stamper.setFormFlattening(true);
                        // 关闭资源
                        stamper.close();
                        // 将ByteArray字节数组中的流输出到out中(即输出到浏览器)
                        Document doc = new Document();
                        PdfCopy copy = new PdfCopy(doc, out);
                        doc.open();
                        PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);
                        copy.addPage(importPage);
                        doc.close();
                        log.info("*****************************PDF导出成功*********************************");
                } catch (Exception e) {
                        e.printStackTrace();
                } finally {
                        try {
                                if (out != null) {
                                        out.flush();
                                        out.close();
                                }
                                if (reader != null) {
                                        reader.close();
                                }
                        } catch (Exception e) {
                                e.printStackTrace();
                        }
                }
        }

 

posted @ 2025-06-27 17:22  悠悠乃  阅读(445)  评论(0)    收藏  举报