2

I use the primefaces extensions documentViewer to show pdfs. The files are streamed, this means the backing bean provides an instance of org.primefaces.model.DefaultStreamedContent. If a big pdf is shown, it took some time until the viewer is showing something. In the showcase of the PF extensions website, the documentViewer shows a loading bar under the viewers button bar. Unfortunately this is not shown in my case. In the showcase there is no DefaultStreamContent used. It is url to file. Maybe I have to set the total size for the streamed content? Is that possible with DefaultStreamedContent?

opfau
  • 731
  • 9
  • 37
  • 1
    *"Maybe I have to set the total size for the streamed content?"* Yes! In flavor of `response.setContentLength(contentLength)`. Then the client can calculate the progress. – BalusC Nov 04 '15 at 12:58
  • Ok, haven't thought about that.Unfortunately I cannot verify it because I figured out that our backend model does not deliver a reliable size. If the size is set too big, the viewer shows a PDFException. – opfau Nov 04 '15 at 13:46
  • It must be the exact size (i.e. the amount of bytes). Do you mean to say that your PDFs are autogenerated on the fly based on arbitrary data and thus not (temporarily) statically stored in some data store? – BalusC Nov 04 '15 at 14:18
  • 1
    Related: http://stackoverflow.com/q/25430677 – BalusC Nov 04 '15 at 14:22
  • Wrong sizes due to issues with encryption. – opfau Nov 04 '15 at 14:26
  • As you can see on related question, an alternative may be to write it to a temp file on disk and then stream it instead. Content length is readily available via `File#length()`. – BalusC Nov 04 '15 at 14:27
  • I can't do that. One reason is security. I don't set the size because the wrong sizes could crash the viewer. So it is better to do it without setting the size in my case. – opfau Nov 04 '15 at 14:30
  • Then just don't set/guess a wrong size? When you generate PDF to file, you will ultimately have the right size via `File#length()` which is safe to be set as content length header. – BalusC Nov 04 '15 at 14:31
  • The setting of `response.setContentLength(contentLength)` works. The loading bar is displayed in the `pe:documentViewer`. But I cannot mark your comment as answer. – opfau Nov 06 '15 at 09:41
  • I can't tell from top of head how that integrates with ``. – BalusC Nov 06 '15 at 09:52
  • So I have to answer this question myself and reference to your comment? – opfau Nov 06 '15 at 10:35
  • I just briefly looked at `` showcase example, but I had an "Eeeek" moment because the example bean over there is very definitely not threadsafe (and memory hogging). I posted an answer with a more robust example. – BalusC Nov 06 '15 at 10:53

1 Answers1

2

Maybe I have to set the total size for the streamed content

Yes! The client can only calculate the progress if the response content length is known beforehand. In JSF, you can set the response content length via ExternalContext#setResponseContentLength().

Provided that you want to return a StreamedContent, here's how you could do it (based on a.o. Display dynamic image from database with p:graphicImage and StreamedContent):

@ManagedBean
@ApplicationScoped
public class PdfManager {

    @EJB
    private PdfService service;

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

        if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
            return new DefaultStreamedContent();
        } else {
            Pdf pdf = service.generateItSomehow();
            context.getExternalContext().setResponseContentLength(pdf.getLength());
            return new DefaultStreamedContent(pdf.getInputStream());
        }
    }

}
Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555