html - PDF 文件合并:删除页尾的空白。我正在使用 PDFBox v2.0.13 来实现这一点
问题描述
我正在使用 PDFBox (v2.0.13) 合并 PDF 文件。
这些文件是
合并后的文件是
我可以删除使第 2 页变为第 1 页的空白吗?
关于合并代码,我使用 pdfbox github 示例代码:https
://github.com/apache/pdfbox/blob/trunk/examples/src/main/java/org/apache/pdfbox/examples/util/PDFMergerExample.java
表在 html 中,它的父元素的边距和填充为 0。代码如下
<div class="table-wrap">
<table id="arOpenItemDetail_save" border="0" cellspacing="1" cellpadding="1" class="table-Y" name="detail">
<THEAD style="display:table-header-group;font-weight:bold" name="detailHeader">
<tr>
<th>Cust#</th>
<th width="20">Order Type</th>
<th>Order No</th>
<th>Doc Terms</th>
<th>Doc Date</th>
<th>Due Date</th>
<th>Days PastDue</th>
<th>Doc Amount</th>
<th>Current</th>
<th>1~30</th>
<th>30+</th>
<th>Ref</th>
<th>Ref2</th>
<th>Reason Code</th></tr>
</THEAD>
<span th:each="detail:${list}">
<tr class="odd">
<td align="right" width="20" th:text="${detail.custNo}">1</td>
<td align="center" width="20" th:text="${detail.custNo}">1</td>
<td align="right" th:text="${detail.custNo}">1</td>
<td align="center" th:text="${detail.custNo}">1</td>
<td align="right" th:text="${detail.custNo}">1</td>
<td align="right" th:text="${detail.custNo}">1</td>
<td align="right" th:text="${detail.custNo}"></td>
<td align="right" th:text="${detail.custNo}"></td>
<td align="right" th:text="${detail.custNo}"></td>
<td align="right" th:text="${detail.custNo}"></td>
<td align="right" th:text="${detail.custNo}"></td>
<td align="left" th:text="${detail.custNo}"></td>
<td align="left" th:text="${detail.custNo}"></td>
<td align="left" th:text="${detail.custNo}"></td>
</tr>
</span>
</table>
</div>
解决方案
这个问题本质上是关于一个或多个 PDF 的多个 PDF 页面的密集合并。
通常 pdf 的合并方法仅基于页面合并,即它们从文档中获取页面以合并并使用所有这些页面创建一个新文档。由于页眉、页脚、背景图形和其他工件在这种情况下必须被识别和忽略,因此更密集的合并(将多个页面的内容放在单个结果页面上)通常是不可行的。对于像您这样的页面,密集合并是可行的,只是尚未作为单一实用程序方法提供。
可以像这样实现这样的实用程序类:
public class PdfDenseMergeTool {
public PdfDenseMergeTool(PDRectangle size, float top, float bottom, float gap)
{
this.pageSize = size;
this.topMargin = top;
this.bottomMargin = bottom;
this.gap = gap;
}
public void merge(OutputStream outputStream, Iterable<PDDocument> inputs) throws IOException
{
try
{
openDocument();
for (PDDocument input: inputs)
{
merge(input);
}
if (currentContents != null) {
currentContents.close();
currentContents = null;
}
document.save(outputStream);
}
finally
{
closeDocument();
}
}
void openDocument() throws IOException
{
document = new PDDocument();
newPage();
}
void closeDocument() throws IOException
{
try
{
if (currentContents != null) {
currentContents.close();
currentContents = null;
}
document.close();
}
finally
{
this.document = null;
this.yPosition = 0;
}
}
void newPage() throws IOException
{
if (currentContents != null) {
currentContents.close();
currentContents = null;
}
currentPage = new PDPage(pageSize);
document.addPage(currentPage);
yPosition = pageSize.getUpperRightY() - topMargin + gap;
currentContents = new PDPageContentStream(document, currentPage);
}
void merge(PDDocument input) throws IOException
{
for (PDPage page : input.getPages())
{
merge(input, page);
}
}
void merge(PDDocument sourceDoc, PDPage page) throws IOException
{
PDRectangle pageSizeToImport = page.getCropBox();
BoundingBoxFinder boundingBoxFinder = new BoundingBoxFinder(page);
boundingBoxFinder.processPage(page);
Rectangle2D boundingBoxToImport = boundingBoxFinder.getBoundingBox();
double heightToImport = boundingBoxToImport.getHeight();
float maxHeight = pageSize.getHeight() - topMargin - bottomMargin;
if (heightToImport > maxHeight)
{
throw new IllegalArgumentException(String.format("Page %s content too large; height: %s, limit: %s.", page, heightToImport, maxHeight));
}
if (gap + heightToImport > yPosition - (pageSize.getLowerLeftY() + bottomMargin))
{
newPage();
}
yPosition -= heightToImport + gap;
LayerUtility layerUtility = new LayerUtility(document);
PDFormXObject form = layerUtility.importPageAsForm(sourceDoc, page);
currentContents.saveGraphicsState();
Matrix matrix = Matrix.getTranslateInstance(0, (float)(yPosition - (boundingBoxToImport.getMinY() - pageSizeToImport.getLowerLeftY())));
currentContents.transform(matrix);
currentContents.drawForm(form);
currentContents.restoreGraphicsState();
}
PDDocument document = null;
PDPage currentPage = null;
PDPageContentStream currentContents = null;
float yPosition = 0;
final PDRectangle pageSize;
final float topMargin;
final float bottomMargin;
final float gap;
}
(PdfDenseMergeTool实用程序类)
它使用BoundingBoxFinder
从这个答案到一个较旧问题的类。
你可以PdfDenseMergeTool
这样使用:
PDDocument document1 = ...;
PDDocument document2 = ...;
PDDocument document3 = ...;
PDDocument document4 = ...;
PDDocument document5 = ...;
PdfDenseMergeTool tool = new PdfDenseMergeTool(PDRectangle.A4, 30, 30, 10);
tool.merge(new FileOutputStream("Merge with Text.pdf"),
Arrays.asList(document1, document2, document3, document4, document5,
document1, document2, document3, document4, document5,
document1, document2, document3, document4, document5));
连续三次合并五个源文档。
对于我的测试文档(每个源文档包含三行文本),我得到以下结果:
第 1 页:
第2页:
这个实用程序类本质上是这个答案PdfDenseMergeTool
中 iText 的一个端口。
它已经使用当前的 PDFBox 3.0.0 开发分支 SNAPSHOT 进行了测试。
推荐阅读
- c - 混淆指针和数组
- powershell - 如何从 powershell 脚本中删除特定单词?
- compilation - 如何使用 GNAT 编译 Ada 项目(已经在青山编译)
- python - 在 Python 3.7 中将 JSON 嵌套到数据框
- html - 焦点旁边的输入时如何更改标签的颜色?
- sql - 包含临时表和游标的存储过程不起作用
- azure - Azure 和虚拟机上的 Cloud Foundry
- javascript - 使用 ajax 更新表单后自动对焦不起作用
- angular - 如何将组件数据对象传递给管道
- javascript - 从 url 获取对象以使用 jsbarcode 呈现条形码