IO系列-- JAVA PDF合并

前言

本章主要讲解JAVA中怎么进行PDF合并 并响应给前端 前端进行预览操作

IO实战代码 主要是记录一些常用 但是很容易忘记的IO流操作

欢迎查看👉🏻👉🏻👉🏻JAVA IO 专栏 查漏补缺 指教一二

虽然你现在用不到 但是未来你一定用得到 🥸

POM依赖

引入下方依赖 后续代码都是在这个版本进行开发 不同版本可能会有些依赖报错

pom 复制代码
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itext7-core</artifactId>
    <version>7.1.16</version>
    <type>pom</type>
</dependency>

java代码

文档合并

java 复制代码
/**
 * 将pdf文档转换成字节数组
 *
 * @return 返回对应PDF文档的字节数组
 */
private static byte[] getPdfBytes(InputStream inputStream) throws Exception {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    byte[] data = new byte[2048];
    int len;
    while ((len = inputStream.read(data)) != -1) {
        out.write(data, 0, len);
    }
    return out.toByteArray();
}

/**
 * 基于内存中的字节数组进行PDF文档的合并
 *
 * @param firstPdf  第一个PDF文档
 * @param secondPdf 第二个PDF文档
 */
private static byte[] mergePdfBytes(byte[] firstPdf, byte[] secondPdf) {
    try {
        if (firstPdf != null && secondPdf != null) {
            // 创建字节数组,基于内存进行合并
            ByteArrayOutputStream bass = new ByteArrayOutputStream();
            PdfDocument destDoc = new PdfDocument(new PdfWriter(bass));
            // 合并的pdf文件对象
            PdfDocument firstDoc = new PdfDocument(new PdfReader(new ByteArrayInputStream(firstPdf)));
            PdfDocument secondDoc = new PdfDocument(new PdfReader(new ByteArrayInputStream(secondPdf)));
            // 合并对象
            PdfMerger merger = new PdfMerger(destDoc);
            merger.merge(firstDoc, 1, firstDoc.getNumberOfPages());
            merger.merge(secondDoc, 1, secondDoc.getNumberOfPages());
            // 关闭文档流
            merger.close();
            firstDoc.close();
            secondDoc.close();
            destDoc.close();
            return bass.toByteArray();
        }
    } catch (IOException e) {
        e.printStackTrace();
        log.error("合并PDF文件失败 {}", e.getMessage());
    }
    return null;
}

调用

参数 List<InputStream> inputStreamList 自行将pdf转换 是需要合并的pdf流

例如: // xxx.pdf 填入pdf 路径路径 InputStream fileInputStream = new FileInputStream(new File("xxx.pdf"));

java 复制代码
/**
 * @param response        响应
 * @param inputStreamList 文件流列表
 * @throws Exception 异常处理
 */
private void handleResponse(HttpServletResponse response,
                            List<InputStream> inputStreamList) throws Exception {
    if (CollUtil.isNotEmpty(inputStreamList)) {
        // 处理响应
        int size = inputStreamList.size();
        byte[] pdfData = getPdfBytes(inputStreamList.get(0));
        for (int i = 1; i < size; i++) {
            pdfData = mergePdfBytes(pdfData, getPdfBytes(inputStreamList.get(i)));
        }
        if (pdfData != null) {
            response.setContentType("application/pdf");
            response.setHeader("Content-Disposition", "attachment; filename=merged.pdf");

            try (OutputStream outputStream = response.getOutputStream()) {
                outputStream.write(pdfData);
                outputStream.flush();
            }
        }
    }
}

代码直接复制后段合并逻辑就处理完成了

前端接收

因为请求方式不同所有自行修改 只是给一个例子

请求一定要带上 responseType: "blob"

js 复制代码
export function expressService(waybillNoList) {
  return request({
    url: 'xxx' ,
    method: 'get',
    responseType: "blob"
  })
}

预览打印

js 复制代码
   async expressServiceData() {
            try {
                this.buttonLoading = true;
                const response = await expressService(this.expressServicelist);
                this.buttonLoading = false;

                const pdfBlob = new Blob([response.data], {
                    type: "application/pdf",
                });
                const blobUrl = URL.createObjectURL(pdfBlob);

                const printWindow = window.open(blobUrl, "_blank");

                // 等待新窗口加载完成后触发打印
                printWindow.onload = function () {
                    printWindow.print();
                };
            } catch (error) {
                this.buttonLoading = false;
                console.error("Error calling expressService:", error);
            }
        },

效果

相关推荐
开心工作室_kaic1 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
刚刚好ā1 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
qq_17448285751 小时前
springboot基于微信小程序的旧衣回收系统的设计与实现
spring boot·后端·微信小程序
锅包肉的九珍2 小时前
Scala的Array数组
开发语言·后端·scala
心仪悦悦2 小时前
Scala的Array(2)
开发语言·后端·scala
沉默璇年2 小时前
react中useMemo的使用场景
前端·react.js·前端框架
yqcoder2 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
2401_882727572 小时前
BY组态-低代码web可视化组件
前端·后端·物联网·低代码·数学建模·前端框架
心仪悦悦3 小时前
Scala中的集合复习(1)
开发语言·后端·scala
SoaringHeart3 小时前
Flutter进阶:基于 MLKit 的 OCR 文字识别
前端·flutter