An easy way to expose a resource for download
Write a seam component that returns a resource object:
@Name("foo")
...
public Resource getFile() {
return new Resource() {
public Object getContentType() {
return "application/pdf";
}
public byte[] getContent() throws IOException {
// Load data
}
public String getFileName() {
return "file.pdf";
}
public Disposition getDisposition() {
return Disposition.ATTACHMENT;
}
};
}
...
Wire it using pages.xml
...
<page view-id="/file.pdf.xhtml" action="#{foo.file.render}" ></page>
...
And access it from the browser http://localhost:8080/myApp/file.pdf.jsf.
Here is the code for Resource
import java.io.IOException;
import javax.faces.context.FacesContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import org.jboss.seam.Component;
public abstract class Resource {
public void render() throws IOException {
FacesContext facesContext = (FacesContext) Component.getInstance("facesContext");
if (!facesContext.getResponseComplete()) {
HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
response.setContentType(getContentType().toString());
response.setContentLength(getContentSize());
if (Disposition.ATTACHMENT.equals(getDisposition())) {
response.setHeader("Content-disposition", "attachment; filename=" + getFileName());
}
ServletOutputStream out = response.getOutputStream();
out.write(getContent());
out.flush();
facesContext.responseComplete();
}
}
public enum Disposition {
INLINE, ATTACHMENT;
}
public abstract Object getContentType();
public abstract byte[] getContent() throws IOException;
public int getContentSize() throws IOException {
return getContent().length;
}
public String getFileName() {
return "";
}
public Disposition getDisposition() {
return Disposition.INLINE;
}
}
Note that this doesn't work on portals / portlets
Comments