PDF-файлы объединяются: убирайте пробел в конце страницы.Я использую PDFBox v2.0.13 для достижения этой цели - PullRequest
0 голосов
/ 21 января 2019

Я использую PDFBox (v2.0.13) для объединения файлов PDF.
Эти файлы

enter image description here

enter image description here

И объединенный файл -

enter image description here

Можно ли удалить пробел, который сделает 2-ю страницу первой страницей?
О коде слияния, я использую 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> 

1 Ответ

0 голосов
/ 12 февраля 2019

Этот вопрос, по сути, касается плотного объединения нескольких страниц 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:

result page 1

Страница 2:

result page 2


Этот служебный класс по существу является портом PdfDenseMergeTool для iText в этот ответ .

Он был протестирован с текущимPDFBox 3.0.0 ветка разработки SNAPSHOT.

...