【Java】利用 PDF 多页模板生成多个 PDF 后压缩成 ZIP 并导出

文章描述了一个Java工具类PdfUtil,它能根据模板生成多个PDF文件,然后将这些PDF压缩成ZIP。使用了Hutool和iTextPDF库,解决了中文字体问题并支持HTTP响应输出。

一、所需要的依赖

<dependencies>
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>5.3.8</version>
    </dependency>
    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>itextpdf</artifactId>
        <version>5.5.11</version>
   	</dependency>
</dependencies>

二、工具类代码

package ...

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapUtil;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.*;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class PdfUtil {
    
    /**
     * 根据模板生成多个 pdf 并压缩为 zip 文件
     *
     * @param templateName 模板名称(在 resources 文件夹下)
     * @param zipName      压缩包名称
     * @param map          String:传文件名,Object:传 Map<String, String> 对应 pdf 模板里面的字段值
     * @param response     响应对象
     */
    public static void pdfExportPagePlus(String templateName, String zipName, Map<String, Object> map, HttpServletResponse response) {
        OutputStream out = null;
        try {
            // String:被压缩的文件名,byte[]:被压缩的文件流
            List<Map<String, byte[]>> baisBytes = CollUtil.newArrayList();
            for (String fileName : map.keySet()) {
                Map<String, String> inputMap = Convert.toMap(String.class, String.class, map.get(fileName));
                // 将生成 pdf 转化为输入流返回
                ByteArrayOutputStream bos = new ByteArrayOutputStream();

                // 读取pdf模板
                InputStream inputStream = PdfUtil.class.getClassLoader().getResourceAsStream(templateName);

                PdfReader reader = new PdfReader(inputStream);
                PdfStamper stamper = new PdfStamper(reader, bos);
                // 获取模板所有域参数
                AcroFields form = stamper.getAcroFields();
                // 解决中文字体不显示的问题
                BaseFont baseFont = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
                ArrayList<BaseFont> fontArrayList = new ArrayList<BaseFont>();
                fontArrayList.add(baseFont);
                form.setSubstitutionFonts(fontArrayList);
                // 文字类的内容处理
                for (String key : inputMap.keySet()) {
                    String value = inputMap.get(key);
                    form.setField(key, value);
                }
                stamper.setFormFlattening(true);
                stamper.close();
                reader.close();

                byte[] xmpMetadata = bos.toByteArray();
                HashMap<String, byte[]> insertMap = MapUtil.newHashMap();
                insertMap.put(fileName, xmpMetadata);
                baisBytes.add(insertMap);
            }

            // -------------------- 多个 pdf 压缩在 zip 里面  ------------------------

            // 1.创建字节数组输出流,用于返回压缩后的输出流字节数组
            out = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(zipName, "UTF-8"));
            // 2.创建压缩输出流
            ZipOutputStream zipOutStream = new ZipOutputStream(out);
            // 3.遍历要批量压缩的集合文件流
            ByteArrayInputStream bais;
            String fileName;
            int temp;
            for (Map<String, byte[]> tempMap : baisBytes) {
                fileName = tempMap.keySet().iterator().next();
                // 3.1.将需要压缩的字节输出流,转为字节数组输入流
                bais = new ByteArrayInputStream(tempMap.get(fileName));
                // 3.2.设置ZipEntry对象,并对需要压缩的文件命名
                zipOutStream.putNextEntry(new ZipEntry(fileName));
                // 3.3.读取要压缩的字节输出流,进行压缩
                while ((temp = bais.read()) != -1) {
                    // 压缩输出
                    zipOutStream.write(temp);
                }
                // 3.4.关闭流
                bais.close();
            }
            // 4.关闭流
            zipOutStream.close();
        } catch (IOException | DocumentException e) {
            System.out.println(e);
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

三、参考

使用 java.util.zip 对生成的 ByteArrayOutputStream(字节数组输出文件流)进行打包压缩(单个、批量),并返回压缩包文件的字节数组输出文件流用于(文件不落地)下载

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值