gpt4 book ai didi

pdf - PrimeFaces p :media not working with StreamedContent in a @ViewScoped bean

转载 作者:行者123 更新时间:2023-12-01 16:32:30 31 4
gpt4 key购买 nike

我遇到了与浏览器中 Primefaces4 meida 类型渲染 pdf 文件相关的问题。我已经成功尝试了 primefaces 网站展示中的示例。现在我想要一个新功能,它提供了一个树结构,左侧面板中带有文档节点。用户可以选择一个文档将其显示在中央面板中。这意味着一旦用户选择树上的一个文档,它就会在 backbean 中生成 pdf 媒体字段。

相关代码如下:

后台 bean :

@ManagedBean
@ViewScoped
public class DocumentsBean implements Serializable {

private static final long serialVersionUID = 3560539268513760978L;
private TreeNode root;
private String url;
private TreeNode selectedNode;
private StreamedContent media;

public DocumentsBean() {
root = new DefaultTreeNode("Root");
}

public TreeNode getRoot() {
return root;
}

public TreeNode getSelectedNode() {
return selectedNode;
}

public void setSelectedNode(TreeNode selectedNode) {
this.selectedNode = selectedNode;
}

public void onNodeSelect(NodeSelectEvent event) {
File file = (File) this.selectedNode.getData();
generatePDF(file);
}

public String getUrl() {
return url;
}

public void setUrl(String url) {
this.url = url;
}

public void explore() {
root = new DefaultTreeNode(new File(this.url), null);
constructDir(root);
}

/**
* construct directory and its sub files.
* @param parent
*/
private void constructDir(TreeNode parent) {
File file = (File) parent.getData();
File[] files = file.listFiles();
for (File f: files) {
if (f.isFile()) {
new DefaultTreeNode("document", f, parent);
} else {
TreeNode subParent = new DefaultTreeNode(f, parent);
constructDir(subParent);
}
}

}

private void generatePDF(File file) {
PDFGenerator generator = new PDFGenerator(file);
File pdf = generator.transformToPDF();

if (pdf != null) {
InputStream stream = null;
try {
stream = new FileInputStream(pdf);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
media = new DefaultStreamedContent(stream, "application/pdf");
}

}

public StreamedContent getMedia() {
return media;
}

}

我的部分观点:

<p:layoutUnit position="west" size="300" header="Directory Content" resizable="false" collapsible="true">
<h:form id="docTree_form">
<p:growl id="messages" showDetail="true" />
<p:tree id="docTree" value="#{documentsBean.root}" var="node" animate="true" selectionMode="single" selection="#{documentsBean.selectedNode}" dynamic="true" cache="true">

<p:ajax event="select" update=":pdf_form:media" listener="#{documentsBean.onNodeSelect}" />
<p:treeNode expandedIcon="ui-icon-folder-open" collapsedIcon="ui-icon-folder-collapsed">
<h:outputText value="#{node.name}" />
</p:treeNode>

<p:treeNode type="document" icon="ui-icon-document">
<h:outputText value="#{node.name}" />
</p:treeNode>
</p:tree>
</h:form>
</p:layoutUnit>

<p:layoutUnit position="center" header="Center" resizable="true">
<h:form id="pdf_form">
<p:media id="media" value="#{documentsBean.media}" player="pdf" width="100%" height="700px">
Your browser can't display pdf
</p:media>
</h:form>
</p:layoutUnit>

当我运行此代码时,没有错误或异常。但是,Firefox 中没有生成 PDF 查看器。真是奇怪!

基于 BalusC 评论的后续问题:

当我的应用程序运行时,我遇到了这个异常:

SEVERE: Servlet.service() for servlet [Faces Servlet] in context with path     [/DocumentViewer_JSF] threw exception
java.lang.NullPointerException
at org.primefaces.application.PrimeResourceHandler.handleResourceRequest(PrimeResourceHandler.java:114)

我发现这一行导致了这个异常:

return new DefaultStreamedContent();

如果我创建一个真正的 pdf 文件,异常就会消失。但如果用户没有选择文件,我真的不希望显示 pdf 文件。

最佳答案

您的具体问题是因为网络浏览器实际上是在物理上完全独立的 HTTP 请求中下载 PDF 文件,而不是基于 JSF 源代码生成和发送 HTML 输出的 HTTP 请求。您可能已经知道 View 作用域 bean 通过 javax.faces.ViewState 绑定(bind)到特定的 JSF View 。隐藏输入字段。如果此更改或不存在,则请求将获得一个新的不同 View 范围 bean 实例。

换句话说,当浏览器通过单独的 HTTP 请求从服务器下载 PDF 文件时,它并没有使用相同的 @ViewScoped bean 实例,而是获得一个全新且完全独立的实例,该实例不具有与绑定(bind)到页面的属性(状态)相同的属性(状态),因此整个 StreamedContent就是null就在那时。

此问题与 <p:media>StreamedContent<p:graphicImage> 的问题本质上有相同的理由和StreamedContent之前已经回答过好几次了:

在您的特定情况下,您需要以 DocumentsBean 的方式重新设计整个集合。支持 bean 通过唯一标识符将 PDF 文件存储在某个位置(例如临时磁盘、服务器内存、数据库等),然后将该唯一标识符作为请求参数传递给 <p:media>如下:

<p:media value="#{mediaManager.stream}" width="100%" height="700px" player="pdf">
<f:param name="id" value="#{documentsBean.mediaId}" />
</p:media>

据此MediaManager支持 bean 看起来像这样:

@ManagedBean
@ApplicationScoped
public class MediaManager {

@EJB
private MediaService service;

public StreamedContent getStream() throws IOException {
FacesContext context = FacesContext.getCurrentInstance();

if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
// So, we're rendering the HTML. Return a stub StreamedContent so that it will generate right URL.
return new DefaultStreamedContent();
} else {
// So, browser is requesting the media. Return a real StreamedContent with the media bytes.
String id = context.getExternalContext().getRequestParameterMap().get("id");
Media media = service.find(Long.valueOf(id));
return new DefaultStreamedContent(new ByteArrayInputStream(media.getBytes()));
}
}

}

关于pdf - PrimeFaces p :media not working with StreamedContent in a @ViewScoped bean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18994288/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com