/**
* 把多个pdf合并成一个pdf,使用新的分页,可以跳页。
*
* @param streamOfPDFFiles 需要合并的所有文件
* @param outputStream 合并后的流
* @param paginate 是否显示页码
* @param patchPageFlag 是否补齐偶数页
*/
public static void concatPDFsByPage(List<InputStream> streamOfPDFFiles, OutputStream outputStream, boolean paginate, boolean patchPageFlag) {
log.info("concatPDFsByPage.....s");
Document document = new Document();
try {
List<Map<String, Object>> pdfReaderList = Lists.newArrayList();
int totalPages = 0;
//遍历每一个pdf流。把不需要页码的index找出来。{pdf流,[1,2,3,4]}
ByteArrayOutputStream byteArrayOutputStream = null;
for (InputStream pdf : streamOfPDFFiles) {
byteArrayOutputStream = new ByteArrayOutputStream();
try {
byte[] buff = new byte[1024];
int rc = 0;
while ((rc = pdf.read(buff, 0, buff.length)) > 0) {
byteArrayOutputStream.write(buff, 0, rc);
}
//获取有标记的页面index。
List<Integer> disablePage = PdfUtils.getExceptPage(byteArrayOutputStream.toByteArray(), "disablePage");
//定义一个reader 来接收
PdfReader pdfReader = null;
if (disablePage.size() > 0) {
pdfReader = new PdfReader(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
} else {
pdfReader = new PdfReader(byteArrayOutputStream.toByteArray());
}
Map<String, Object> map = new HashMap<>(16);
map.put("disablePage", disablePage);
map.put("pdfReader", pdfReader);
pdfReaderList.add(map);
//总页数累加,需要减去不要页码的
totalPages += (pdfReader.getNumberOfPages() - disablePage.size());
pdf.close();
byteArrayOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (pdf != null) {
pdf.close();
}
if (byteArrayOutputStream != null) {
byteArrayOutputStream.close();
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
//设置字体之类的
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
document.open();
BaseFont bf = BaseFont.createFont(ConstantReport.fontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
PdfContentByte cb = writer.getDirectContent();
PdfImportedPage page;
int currentPageNumber = 0;
//游标
int pageOfCurrentReaderPDF = 0;
for (Map map : pdfReaderList) {
//排除的页码
List<Integer> disablePage = (List<Integer>) map.get("disablePage");
//内衬页页,用来标记页码的。pageOfCurrentReaderPDF 也可以。
int pageNumber = 0;
PdfReader pdfReader = (PdfReader) map.get("pdfReader");
int numberOfPages = pdfReader.getNumberOfPages();
while (pageOfCurrentReaderPDF < numberOfPages) {
//变量累加
pageOfCurrentReaderPDF++;
currentPageNumber++;
pageNumber++;
//获取原pdf的方向,并且设置新的页的方向
document.setPageSize(pdfReader.getPageSize(pdfReader.getPageN(pageOfCurrentReaderPDF)));
document.newPage();
page = writer.getImportedPage(pdfReader, pageOfCurrentReaderPDF);
cb.addTemplate(page, 0, 0);
if (paginate) {
//如果排除页数组包含当前页。那么就pass,不生成页码
if (!disablePage.contains(pageNumber)) {
cb.beginText();
cb.setFontAndSize(bf, 11);
cb.showTextAligned(PdfContentByte.ALIGN_CENTER, "第 " + (currentPageNumber) + " 页 共 " + (totalPages) + " 页", ConstantReport.pageFooterX, ConstantReport.pageFooterY, 0);
cb.endText();
} else {
//如果包含排除页,那么就减一
currentPageNumber--;
}
}
}
if (patchPageFlag) {
log.info("当前pdf总页数:{},准备增加空白页?:{}", numberOfPages, numberOfPages % 2 > 0);
//如果总页数是奇数,那么补空白页
if (numberOfPages % 2 > 0) {
document.newPage();
writer.setPageEmpty(false);
log.info("已经增加空白页");
}
}
pageOfCurrentReaderPDF = 0;
}
outputStream.flush();
document.close();
outputStream.close();
log.info("concatPDFsByPage.....e");
} catch (Exception e) {
log.error(e.getMessage());
} finally {
if (document.isOpen()) {
document.close();
}
try {
if (outputStream != null) {
outputStream.close();
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
应项目要求,使用帆软生成pdf后,需要把多个分项pdf,合成一个总体报告,并且过滤掉部分pdf,不合成,并且合成后需要生成页码,并且页码要可以跳pdf生成。比如第一张需要页码,第二张不需要页码,第三张需要。
分享给大家,如果有更好的方法,欢迎分享。
2020年5月15日 新增:
1、优化流关闭
2、增加新需求,为了能双面打印,新增空白页。