您還可以使用組件系統事件(特別是PreRenderViewEvent)在JSF 2.0中解決此問題。
只需創建一個下載視圖(/download.xhtml),它在渲染之前觸發下載偵聽器。
<?xml version="1.0" encoding="UTF-8"?>
<f:view
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core">
<f:event type="preRenderView" listener="#{reportBean.download}"/>
</f:view>
然後,在你的報告豆,你把文件和標記響應,完整(使用JSR-299定義)。
public @Named @RequestScoped class ReportBean {
public void download() throws Exception {
FacesContext ctx = FacesContext.getCurrentInstance();
pushFile(
ctx.getExternalContext(),
"/path/to/a/pdf/file.pdf",
"file.pdf"
);
ctx.responseComplete();
}
private void pushFile(ExternalContext extCtx,
String fileName, String displayName) throws IOException {
File f = new File(fileName);
int length = 0;
OutputStream os = extCtx.getResponseOutputStream();
String mimetype = extCtx.getMimeType(fileName);
extCtx.setResponseContentType(
(mimetype != null) ? mimetype : "application/octet-stream");
extCtx.setResponseContentLength((int) f.length());
extCtx.setResponseHeader("Content-Disposition",
"attachment; filename=\"" + displayName + "\"");
// Stream to the requester.
byte[] bbuf = new byte[1024];
DataInputStream in = new DataInputStream(new FileInputStream(f));
while ((in != null) && ((length = in.read(bbuf)) != -1)) {
os.write(bbuf, 0, length);
}
in.close();
}
}
這就是它的全部!
您可以鏈接到下載頁面(/download.jsf),也可以使用HTML元標記在啓動頁面上重定向到它。
我試過這個解決方案。它只有在頁面沒有其他控制的情況下才有效。如果頁面具有其他控件(如下拉框選擇),並且頁面來回多次,則「download()」將繼續調用並且該值將永久重置。因此,有沒有辦法永遠保護它的執行只有一次? – huahsin68 2012-08-30 02:33:48