一、所需要的依赖
<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(字节数组输出文件流)进行打包压缩(单个、批量),并返回压缩包文件的字节数组输出文件流用于(文件不落地)下载