Show PDF Files With PrimeFaces

It is pretty easy to preview pdf files with PrimeFaces media component as explained in official page.

If you try this already there are two common problems that may find you.

  • Shows the same file every time
  • Cannot download the file multiple times (if you have an extra download button even the pdf viewer already have one)

To solve the first problem we generate an id for each media file to disable cache [1] .

The main reason of the second problem is that ‘a stream can be read only once’, so simply we have to refill the stream after every download attempt, but how can we understand that download is completed? Fortunately, PrimeFaces gives us some functions to probing download process [2] .

Here is the complete example:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;
@ApplicationScoped
@ManagedBean
public class FormView {
private StreamedContent streamedContent;
private List<MyFile> files = new ArrayList<MyFile>();
private String selectedFileName;
@PostConstruct
public void init() {
MyFile myFile1 = new MyFile(1, "1.pdf");
MyFile myFile2 = new MyFile(2, "2.pdf");
files.add(myFile1);
files.add(myFile2);
}
public List<MyFile> getFiles() {
return files;
}
public String getSelectedFileName() {
return selectedFileName;
}
public void setSelectedFileName(String selectedFileName) {
this.selectedFileName = selectedFileName;
}
public StreamedContent getStreamedContent() {
return streamedContent;
}
public void setStreamedContent(StreamedContent streamedContent) {
this.streamedContent = streamedContent;
}
public void onRowSelect(SelectEvent event) {
String fileName = ((MyFile) event.getObject()).getName();
// we use this for refill the stream
selectedFileName = fileName;
createStream(fileName);
}
private StreamedContent createStream(String fileName) {
streamedContent = new DefaultStreamedContent(getData(fileName), "application/pdf", "downloaded_" + fileName);
return streamedContent;
}
private InputStream getData(String fileName) {
// pdf files under src\main\resources
File file = new File(System.getProperty("user.dir") + "\\src\\main\\resources\\" + fileName);
InputStream is = null;
try {
is = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return is;
}
// refill the stream
public void refreshStream() {
createStream(selectedFileName);
}
public String generateRandomIdForNotCaching() {
return java.util.UUID.randomUUID().toString();
}
}
view raw FormView.java hosted with ❤ by GitHub
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<h2>Page No.1</h2>
<p:dataTable var="file" value="#{formView.files}" selectionMode="single" rowKey="#{file.id}" style="width:50%">
<p:ajax event="rowSelect" listener="#{formView.onRowSelect}" oncomplete="PF('dlg1').show()" update=":form" />
<p:column headerText="Name">
<h:outputText value="#{file.name}" />
</p:column>
</p:dataTable>
<p:dialog header="Dialog" widgetVar="dlg1" modal="false">
<h:form id="form">
<p:messages id="msgs" />
<h:panelGrid columns="1" cellpadding="5">
<p:media value="#{formView.streamedContent}" player="pdf" width="600px" height="300px">
<f:param name="id" value="#{formView.generateRandomIdForNotCaching()}" />
</p:media>
<p:commandButton value="download" ajax="false" onclick="PrimeFaces.monitorDownload(startOffer, stopOffer);">
<p:fileDownload value="#{formView.streamedContent}" />
</p:commandButton>
</h:panelGrid>
</h:form>
</p:dialog>
<h:form>
<p:remoteCommand name="refreshStreamOffer" actionListener="#{formView.refreshStream()}" />
</h:form>
<script type="text/javascript">
function startOffer() {
refreshStreamOffer();
}
function stopOffer() {
refreshStreamOffer();
}
</script>
</h:body>
</html>
view raw index.xhtml hosted with ❤ by GitHub
public class MyFile {
private Integer id;
private String name;
public MyFile(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
view raw MyFile.java hosted with ❤ by GitHub

[1] http://stackoverflow.com/questions/18994288/primefaces-update-pdf-media-not-working

[2] http://www.primefaces.org/showcase/ui/file/download.xhtml

2 thoughts on “Show PDF Files With PrimeFaces

  1. Stanley Shi says:

    Good explanation.
    Thank you!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: