You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache FOP使用PDF作为背景时出现COSStream已关闭无法读取异常

问题场景

我使用Apache FOP 2.5.x版本生成PDF文件,需要将现有PDF作为背景图,因此引入fop-pdf-images-2.3依赖实现该能力,该组件依赖PDFBox 2.0.20支撑FOP读取PDF作为背景图的需求。
运行过程中偶发如下报错:

Error on PDF page: https://s2.q4cdn.com/498544986/files/doc_downloads/test.pdf COSStream has been closed and cannot be read. Perhaps its enclosing PDDocument has been closed?
    at org.apache.fop.render.pdf.pdfbox.PDFBoxImageHandler.handleImage(PDFBoxImageHandler.java:84)
    at org.apache.fop.render.intermediate.AbstractIFPainter.drawImage(AbstractIFPainter.java:249)
    at org.apache.fop.render.intermediate.AbstractIFPainter.drawImage(AbstractIFPainter.java:205)
    at org.apache.fop.render.intermediate.AbstractIFPainter.drawImageUsingImageHandler(AbstractIFPainter.java:170)
    at org.apache.fop.render.pdf.PDFPainter.drawImageUsingURI(PDFPainter.java:218)
    at org.apache.fop.render.pdf.PDFPainter.drawImage(PDFPainter.java:181)
    at org.apache.fop.render.intermediate.IFRenderer.drawImage(IFRenderer.java:1301)
    at org.apache.fop.render.AbstractPathOrientedRenderer.drawImage(AbstractPathOrientedRenderer.java:973)
    at org.apache.fop.render.AbstractPathOrientedRenderer.drawBackground(AbstractPathOrientedRenderer.java:308)
    at org.apache.fop.render.intermediate.IFRenderer.drawBackground(IFRenderer.java:1390)
    at org.apache.fop.render.AbstractPathOrientedRenderer.drawBackground(AbstractPathOrientedRenderer.java:215)
    at org.apache.fop.render.AbstractPathOrientedRenderer.drawBackAndBorders(AbstractPathOrientedRenderer.java:173)
    at org.apache.fop.render.AbstractPathOrientedRenderer.handleRegionTraits(AbstractPathOrientedRenderer.java:128)
    at org.apache.fop.render.AbstractRenderer.renderRegionViewport(AbstractRenderer.java:373)
    at org.apache.fop.render.intermediate.IFRenderer.renderRegionViewport(IFRenderer.java:738)
    at org.apache.fop.render.AbstractRenderer.renderPageAreas(AbstractRenderer.java:345)
    at org.apache.fop.render.AbstractRenderer.renderPage(AbstractRenderer.java:318)
    at org.apache.fop.render.intermediate.IFRenderer.renderPage(IFRenderer.java:587)
    at org.apache.fop.area.RenderPagesModel.addPage(RenderPagesModel.java:123)
    at org.apache.fop.layoutmgr.AbstractPageSequenceLayoutManager.finishPage(AbstractPageSequenceLayoutManager.java:316)
    at org.apache.fop.layoutmgr.PageSequenceLayoutManager.finishPage(PageSequenceLayoutManager.java:243)
    at org.apache.fop.layoutmgr.PageSequenceLayoutManager.activateLayout(PageSequenceLayoutManager.java:147)
    at org.apache.fop.area.AreaTreeHandler.endPageSequence(AreaTreeHandler.java:267)
    at org.apache.fop.fo.pagination.PageSequence.endOfNode(PageSequence.java:139)
    at org.apache.fop.fo.FOTreeBuilder$MainFOHandler.endElement(FOTreeBuilder.java:362)
    at org.apache.fop.fo.FOTreeBuilder.endElement(FOTreeBuilder.java:190)
    ...省略剩余栈帧
Caused by: java.io.IOException: COSStream has been closed and cannot be read. Perhaps its enclosing PDDocument has been closed?
    at org.apache.pdfbox.cos.COSStream.checkClosed(COSStream.java:154)
    at org.apache.pdfbox.cos.COSStream.createInputStream(COSStream.java:239)
    at org.apache.pdfbox.cos.COSStream.createInputStream(COSStream.java:234)
    at org.apache.pdfbox.pdmodel.PDPage.getContents(PDPage.java:157)
    at org.apache.fop.render.pdf.pdfbox.PDFBoxAdapter.getContents(PDFBoxAdapter.java:460)
    at org.apache.fop.render.pdf.pdfbox.PDFBoxAdapter.createStreamFromPDFBoxPage(PDFBoxAdapter.java:352)
    at org.apache.fop.render.pdf.pdfbox.AbstractPDFBoxHandler.createStreamForPDF(AbstractPDFBoxHandler.java:111)
    at org.apache.fop.render.pdf.pdfbox.PDFBoxImageHandler.handleImage(PDFBoxImageHandler.java:71)
    ...省略剩余栈帧

经排查发现该错误与.fo文件中设置的pageHeight、pageWidth参数相关,.fo文件配置如下:

{% set cardWidth = 8.3 %}
{% set cardHeight = 8 %}
{% set bleedLength = 0.125 %}
{% set totalWidth = cardWidth + 2 * bleedLength %}
{% set totalHeight = cardHeight + 2 * bleedLength %}

<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <fo:layout-master-set>
        <fo:simple-page-master master-name="MyPick" page-width="{{ totalWidth }}in" page-height="{{ totalHeight }}in">
            <fo:region-body background-image="https://s2.q4cdn.com/498544986/files/doc_downloads/test.pdf"/>
        </fo:simple-page-master>
    </fo:layout-master-set>
    <fo:page-sequence master-reference="MyPick">
        <fo:flow flow-name="xsl-region-body">
            <fo:block-container absolute-position="absolute" top="{{ bleedLength }}in" left="{{ bleedLength }}in" width="{{ cardWidth }}in" height="{{ cardHeight }}in">
                <fo:block-container display-align="center" margin-left="1.5in" margin-top="1.2in" margin-right="1.5in" height="6.539in">
                    <fo:block-container margin="0">
                        <fo:block font-family="Bookerly Display" text-align="start" color="rgb(255,255,255)" font-size="160pt" line-height="1">
                            Header
                        </fo:block>
                        <fo:block font-family="Bookerly Display" margin-top="0.3in" text-align="start" color="rgb(255,255,255)" font-size="110pt" line-height="1">
                            SubHeader
                        </fo:block>
                    </fo:block-container>
                </fo:block-container>
                <fo:block margin-top="0.75in" margin-bottom="0.4175in" margin-right="0.39in" text-align="right" font-family="Arial" font-size="6pt" color="rgb(255,255,255)">
                    Footer
                </fo:block>
            </fo:block-container>
        </fo:flow>
    </fo:page-sequence>
</fo:root>

将配置中的cardWidth从8.3调整为8.2时,同一份PDF可以正常渲染,异常仅在特定页面尺寸下触发。

问题根因

该异常是fop-pdf-images 2.3版本的已知资源管理缺陷:

  • 当FO设置的页面尺寸和背景PDF的页面尺寸差异达到阈值时,FOP会触发两次背景图渲染逻辑:第一次读取PDF资源做尺寸适配计算,计算完成后组件错误地提前关闭了关联的PDDocument实例;第二次实际渲染需要读取PDF流时,就会抛出COSStream已关闭的报错。
  • 调整cardWidth为8.2后,页面尺寸适配逻辑无需二次读取PDF资源,因此可以正常渲染。
解决方案

方案1:升级依赖(优先推荐)

将fop-pdf-images升级到2.6及以上版本,该版本已修复PDDocument提前关闭的问题,同时将配套依赖的PDFBox版本升级到2.0.24及以上,避免版本兼容冲突,可适配当前使用的Apache FOP 2.5.x版本。

方案2:对齐页面尺寸(无需修改依赖)

提前将背景PDF的页面尺寸调整为和FO配置中totalWidth、totalHeight完全一致的尺寸,避免FOP渲染时触发背景重计算逻辑,即可绕开关流缺陷。

方案3:替换背景格式(应急使用)

如果前两个方案暂时无法落地,可以将背景PDF导出为300DPI以上的PNG图片作为背景使用,绕开PDFBox读取PDF流的逻辑,缺点是会丢失矢量图的无限缩放清晰度,仅适合临时应急。


内容的提问来源于stack exchange,提问作者Suparv Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 18:36:02