Można to również rozwiązać w JSF 2.0 przy użyciu zdarzeń systemu komponentów, w szczególności PreRenderViewEvent.
Po prostu utwórz widok pobierania (/download.xhtml), który uruchamia program nasłuchujący do pobrania przed renderowaniem.
<?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>
Następnie w raporcie fasoli (określone za pomocą JSR-299), kiedy pchasz plik i zaznaczyć odpowiedź jako kompletne.
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();
}
}
To wszystko, o to chodzi!
Możesz połączyć ze stroną pobierania (/download.jsf) lub użyć metatagu HTML, aby przekierować do niego na stronie powitalnej.
Mam spróbować tego rozwiązania. Działa tylko wtedy, gdy strona nie ma innej kontroli. Jeśli strona ma inną kontrolę, np. Wybór pola wyboru, a strona jest kilka razy w przód iw tył, funkcja 'download()' będzie nadal wywoływać, a wartość zostanie na zawsze zresetowana. Czy istnieje zatem sposób, by na zawsze ochronić jego egzekucję na zawsze? – huahsin68