2013-09-25 3 views
3

브라우저에서 Primefaces4 meida type rendering pdf 파일과 관련된 문제가 있습니다. 나는 primefaces 웹 사이트에서 보여준 예제를 성공적으로 시험해 보았습니다. 이제는 왼쪽 패널에 문서 노드가있는 트리 구조를 제공하는 새로운 기능을 원합니다. 사용자는 하나의 문서를 선택하여 중앙 패널에 표시 할 수 있습니다. 즉, 사용자가 트리에서 하나의 문서를 선택하면 pdf 미디어 필드가 백bean에 생성됩니다.primefaces pdf 미디어가 작동하지 않습니다.

관련 코드는 다음과 같습니다 :

backbean : 내보기의

@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 뷰어가 생성되지 않습니다. 정말 이상 하네!

return new DefaultStreamedContent(); 
:

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) 

내가이 줄이 예외를 발생 발견 : BalusC의 의견에 따라

후속 질문 : 내 애플 리케이션가 실행 중일 때

나는이 예외를 가지고

실제 PDF 파일을 만들면 예외가 사라집니다. 그러나 사용자가 파일을 선택하지 않은 경우 pdf 파일이 표시되는 것을 원하지 않습니다.

답변

6

구체적인 문제는 웹 브라우저가 실제로 JSF 소스 코드를 기반으로 HTML 출력을 생성하고 보내는 HTTP 요청과는 완전히 다른 별도의 HTTP 요청으로 PDF 파일을 다운로드하기 때문에 발생합니다. 뷰 범위 Bean은 javax.faces.ViewState 숨겨진 입력 필드를 통해 특정 JSF 뷰에 연결된다는 것을 이미 알고있을 것이다. 이것이 변경되거나 없어지면 요청은 새롭고 다른 뷰 범위의 빈 인스턴스를 얻습니다.

다른 말로하면, 브라우저가 별도의 HTTP 요청으로 서버에서 PDF 파일을 다운로드하는 동안 동일한 @ViewScoped bean 인스턴스를 사용하지 않고 대신 보유하지 않는 아주 새롭고 완전히 독립적 인 인스턴스를 얻습니다 페이지에 연결된 것과 동일한 속성 (상태)이므로 전체 StreamedContent은 그 시점에서 간단히 null입니다.

<p:media>StreamedContent에이 문제는 이전에 여러 번 대답한다 <p:graphicImage>StreamedContent의 문제로 본질적으로 같은 이유가 있습니다

을 너의 특별한 캘리포니아 안에 예를 들어, DocumentsBean 뒷받침 빈이 PDF 파일을 일부 위치에 저장하는 방식으로 전체 묶음을 다시 디자인해야합니다 (예 :다음과 같이 임시 디스크, 고유 식별자에 의해 서버 메모리, 데이터베이스 등) 다음 <p:media>에 요청 매개 변수와 함께 정확히 고유 식별자를 전달합니다

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

를 하였으되이 같은 MediaManager 백업 콩 모양의 무언가 :

@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())); 
     } 
    } 

} 
+0

위대한 작품! 블로그가 정말로 도움이됩니다. 사실 JSF2를 사용하기 시작 했으므로이 문제의 범주를 식별하는 데 너무 많은 경험이 없습니다. 나는 여전히 흡수 중이다. –

+0

반갑습니다. – BalusC

+0

한 줄의 코드를 기반으로 한 후속 질문입니다. –

관련 문제