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

后端 未结 1 2015
囚心锁ツ
囚心锁ツ 2020-12-10 21:18

I have an issue related to Primefaces4 meida type rendering pdf file in browser. I have successfully tried the example in showcase from primefaces website. Now I want to get

相关标签:
1条回答
  • 2020-12-10 21:31

    Your concrete problem is caused because the webbrowser is actually downloading the PDF file in a physically completely separate HTTP request than the HTTP request which is generating and sending the HTML output based on JSF source code. You probably already know that view scoped beans are tied to a particular JSF view via javax.faces.ViewState hidden input field. If this get changed or is absent, then the request gets a new and different view scoped bean instance.

    In other words, while the browser is downloading the PDF file from the server in a separate HTTP request, it isn't using the same @ViewScoped bean instance, but instead getting a brand new and completely independent instance which does not hold the same properties (state) as the one tied to the page and thus the whole StreamedContent is simply null at that point.

    This problem with <p:media> and StreamedContent has essentially the same grounds as the problem with <p:graphicImage> and StreamedContent which is answered several times before:

    • Display dynamic image from database with p:graphicImage and StreamedContent
    • Display database blob images in <p:graphicImage> inside <ui:repeat>
    • How to use p:graphicImage with StreamedContent within p:dataTable?

    In your particular case, you need to redesign the whole bunch in such way that the DocumentsBean backing bean stores the PDF file in some place (e.g. temp disk, server memory, database, etc) by an unique identifier and then pass exactly that unique identifier along as request parameter to <p:media> as follows:

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

    Whereby the MediaManager backing bean look something like this:

    @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 讨论(0)
提交回复
热议问题