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);
            }
        },

效果

相关推荐
计算机魔术师8 小时前
纽约时报版权诉讼披露:微软高管内部称训练 AI 是人类历史上最大规模劳动窃取
前端
去伪存真9 小时前
大模型的参数量为什么那么大?
前端·人工智能
打工仔折腾 AI9 小时前
FastAPI 从本机到生产服务器:Nginx+Gunicorn+Uvicorn 完整部署实录
人工智能·后端·python·nginx·fastapi·gunicorn
IT_陈寒9 小时前
Java空指针这次真把我坑惨了
前端·人工智能·后端
moMo9 小时前
LangChain 到 LangGraph: RAG 知识库改造
后端
用户5743853051110 小时前
元数据驱动的通用 CRUD 后端框架 (3- createBusiness 工厂:三层装配 + 一行出 REST)
后端
高级程序源10 小时前
django大学生创新创业项目管理系统94923-计算机课程设计、毕业设计
javascript·vue.js·spring boot·后端·python·django·课程设计
Sam_Deep_Thinking10 小时前
new Thread()之后发生了什么?
java·后端·面试·程序员
八荒启·交互动画10 小时前
# Web特效020—让 Web 特效真正动起来:时间循环应该怎么接
前端·webgl·网页特效·八荒启-交互动画·八荒启