2013-09-25 2 views
3

У меня есть проблема, связанная с PDF-файлом PDF-файлов Primefaces4 meida в браузере. Я успешно пробовал пример в витрине с сайта web-сайтов. Теперь я хочу получить новую функцию, которая предлагает древовидную структуру с узлами документа на левой панели. Пользователь может выбрать один документ для его отображения на центральной панели. Это означает, что он генерирует поле PDF-файлов в backbean, как только пользователь выбирает один документ на дереве.Обновление шрифтов 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. Действительно странно!

прослеживание вопрос на основе замечаний 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 отображался, если пользователь не выбрал файл.

ответ

6

Ваша конкретная проблема вызвана тем, что веб-браузер фактически загружает PDF-файл в физически полностью отдельный HTTP-запрос, чем HTTP-запрос, который генерирует и отправляет вывод HTML на основе исходного кода JSF. Вероятно, вы уже знаете, что объекты с видимыми областями привязаны к определенному представлению JSF через скрытое поле ввода javax.faces.ViewState. Если это изменится или отсутствует, то запрос получает новый и другой экземпляр экземпляра вида.

Другими словами, в то время как браузер загружает PDF-файл с сервера в отдельный HTTP-запрос, он не использует тот же экземпляр bean-экземпляра @ViewScoped, но вместо этого получает совершенно новый и полностью независимый экземпляр, который не поддерживается те же свойства (состояние), что и привязанные к странице, и, таким образом, весь StreamedContent просто null в этой точке.

Эта проблема с <p:media> и StreamedContent имеет по существу те же основания, что и проблемы с <p:graphicImage> и StreamedContent, который ответил на несколько раз, прежде чем:

В вашем конкретном se, вам нужно переконфигурировать весь пакет таким образом, чтобы резервный bean-компонент 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

следующий вопрос, основанный на одной строке вашего кода. –

Смежные вопросы