java - pdf 合并期间出现 OutOfMemoryError

标签 java pdf merge itext

下面的代码合并 pdf 文件并返回合并的 pdf 数据。当这段代码运行时,我尝试将 100 个文件合并,每个文件大约 500kb,我在 document.close(); 行中收到内存不足错误。这段代码在web环境中运行,是webspehere服务器可用的内存有问题吗?我在一篇文章中读到使用 freeReader 方法,但我不知道如何在我的场景中使用它。

protected ByteArrayOutputStream joinPDFs(List<InputStream> pdfStreams,
        boolean paginate) {

    Document document = new Document();

    ByteArrayOutputStream mergedPdfStream = new ByteArrayOutputStream();

    try {
        //List<InputStream> pdfs = pdfStreams;
        List<PdfReader> readers = new ArrayList<PdfReader>();
        int totalPages = 0;
        //Iterator<InputStream> iteratorPDFs = pdfs.iterator();
        Iterator<InputStream> iteratorPDFs = pdfStreams.iterator();

        // Create Readers for the pdfs.
        while (iteratorPDFs.hasNext()) {
            InputStream pdf = iteratorPDFs.next();
            if (pdf == null)
                continue;
            PdfReader pdfReader = new PdfReader(pdf);
            readers.add(pdfReader);
            totalPages += pdfReader.getNumberOfPages();
        }

        //clear this
        pdfStreams = null;

        //WeakReference ref = new WeakReference(pdfs);
        //ref.clear();

        // Create a writer for the outputstream
        PdfWriter writer = PdfWriter.getInstance(document, mergedPdfStream);
        writer.setFullCompression();

        document.open();
        BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA,
                BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
        PdfContentByte cb = writer.getDirectContent(); // Holds the PDF
        // data

        PdfImportedPage page;
        int currentPageNumber = 0;
        int pageOfCurrentReaderPDF = 0;
        Iterator<PdfReader> iteratorPDFReader = readers.iterator();

        // Loop through the PDF files and add to the output.
        while (iteratorPDFReader.hasNext()) {
            PdfReader pdfReader = iteratorPDFReader.next();

            // Create a new page in the target for each source page.
            while (pageOfCurrentReaderPDF < pdfReader.getNumberOfPages()) {
                pageOfCurrentReaderPDF++;
                document.setPageSize(pdfReader
                        .getPageSizeWithRotation(pageOfCurrentReaderPDF));
                document.newPage();
                // pageOfCurrentReaderPDF++;
                currentPageNumber++;
                page = writer.getImportedPage(pdfReader,
                        pageOfCurrentReaderPDF);
                cb.addTemplate(page, 0, 0);

                // Code for pagination.
                if (paginate) {
                    cb.beginText();
                    cb.setFontAndSize(bf, 9);
                    cb.showTextAligned(PdfContentByte.ALIGN_CENTER, ""
                            + currentPageNumber + " of " + totalPages, 520,
                            5, 0);
                    cb.endText();
                }
            }
            pageOfCurrentReaderPDF = 0;
            System.out.println("now the size is: "+pdfReader.getFileLength());
        }
        mergedPdfStream.flush();
        document.close();
        mergedPdfStream.close();
        return mergedPdfStream;
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (document.isOpen())
            document.close();
        try {
            if (mergedPdfStream != null)
                mergedPdfStream.close();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
    return mergedPdfStream;
}

谢谢 V

最佳答案

此代码将所有 PDF 合并到内存(堆)中的一个数组中,因此,内存使用量将随着合并的文件数量线性增长。

我不知道 freeReader 方法,但也许你可以尝试将合并的 PDF 写入临时文件而不是字节数组? mergedPdfStream 将是 FileOutputStream 而不是 ByteArrayOutputStream。然后你返回,例如对客户端代码的 File 引用。

或者您可以增加 Java 可以使用的内存量(-Xmx JVM 参数),但如果要合并的文件数量最终增加,您会发现自己遇到同样的问题。

关于java - pdf 合并期间出现 OutOfMemoryError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2880851/

相关文章:

java - 以下 LRU 实现的 get 方法中的 map.remove() 有什么用?

java - 从BroadcastReciever内部的startActivityForResult获取结果,调用ACTION_INSTALL_PACKAGE Intent

pdf - 使用名称创建 PDF,而不是在驱动器中创建文件并重命名

git - 仅在本地分支或本地和远程分支上为新功能创建分支?

接口(interface) : from which modules are they invoked? 中的 Java 9 默认方法

java - 哈希表:为什么get方法是同步的?

javascript - 在 PDF 文件中使用 JavaScript 代码的文档

java - 使用 PDFBox 保护 PDF

sql - 如何根据公共(public)值合并数据库行?

python - Pandas DataFrame 列连接