Primefaces 13.0.5 p:media组件加载数据库PDF失败求助
PrimeFaces p:media/pe:documentViewer 无法显示数据库加载的PDF排查
问题现象
使用PrimeFaces 13.0.5的p:media组件,从数据库读取byte[]构建StreamedContent后无法显示PDF,但静态资源路径的PDF可以正常显示;测试PrimeFaces Extensions 13.0.13的pe:documentViewer也出现相同问题,浏览器控制台有报错。
现有代码
后台Bean代码
public StreamedContent getMedia() { StreamedContent result; if (this.selectedRow == null) { return null; } result = DefaultStreamedContent.builder() .contentType("application/pdf") .stream(() -> { try { return new ByteArrayInputStream(this.getSelectedDokument().getDocumentAsByte()); } catch (Exception e) { e.printStackTrace(); return null; } }) .build(); return result; }
XHTML代码
<div class="card"> <h5>PDF</h5> <p:media value="#{controller.getMedia()}" width="100%" height="590px" id="media" cache="false" player="pdf"/> </div>
排查步骤与修复方案
确认PDF内容有效性
将getSelectedDokument().getDocumentAsByte()返回的byte[]写入本地文件,验证是否能正常打开,排除数据库中PDF本身损坏的可能。修复StreamedContent构建逻辑
现有代码存在两处关键问题:异常时静默返回null导致流为空、缺少必要的显示参数。修改后的代码如下:public StreamedContent getMedia() { if (this.selectedRow == null) { throw new FacesException("未选中文档"); } byte[] pdfBytes = this.getSelectedDokument().getDocumentAsByte(); if (pdfBytes == null || pdfBytes.length == 0) { throw new FacesException("文档内容为空"); } return DefaultStreamedContent.builder() .contentType("application/pdf") .contentDisposition(ContentDisposition.INLINE) .filename("document.pdf") .stream(() -> new ByteArrayInputStream(pdfBytes)) .build(); }检查视图状态与请求生命周期
确保selectedRow在请求阶段未丢失:若通过AJAX加载组件,需确认selectedRow未因视图状态失效变为null,否则会返回空的StreamedContent。同时,数据库查询等耗时操作建议提前完成,避免在getMedia()中执行导致请求超时断流。分析浏览器控制台报错
查看控制台具体错误:若为404/500错误,说明流请求接口存在问题;若为PDF解析错误,大概率是流内容损坏或ContentType配置不正确。XHTML代码优化(可选)
将EL表达式中的getMedia()改为属性访问media,符合JSF最佳实践,避免方法被重复调用:<div class="card"> <h5>PDF</h5> <p:media value="#{controller.media}" width="100%" height="590px" id="media" cache="false" player="pdf"/> </div>
内容的提问来源于stack exchange,提问作者Jürgen Hochköppler
相关产品推荐
相关产品推荐

