-
1. Re: how to download a file via Seam& JSF,
tyshan Nov 27, 2007 2:59 AM (in response to tyshan)hi,
emmergency,
how to get a OutputStream from the HttpServletResponse? or can I use a servlet to do that?
Best regards
Tyshan -
2. Re: how to download a file via Seam& JSF,
squ1rr3l Jan 23, 2008 10:38 AM (in response to tyshan)"tyshan" wrote:
hi,
I can upload a file successfully, but failed to download a file.
I get an exception that
Servlet response already use stream, Writer not possible
Same problem here trying to output a Jasper report. Perhaps calling another bean and exposing the generated report binary to JSF would work? -
3. Re: how to download a file via Seam& JSF,
dustismo Jan 23, 2008 11:22 AM (in response to tyshan)FacesContext context = FacesContext.getCurrentInstance(); HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse(); response.setContentType(contentType); //fill in contentType OutputStream os = response.getOutputStream(); os.write(bytes); //fill in bytes os.flush(); os.close(); context.responseComplete();
-Dustin -
4. Re: how to download a file via Seam& JSF,
squ1rr3l Jan 23, 2008 4:14 PM (in response to tyshan)Thanks for the reply. Is that code working for you? Because that's exactly what I tried, but I get the
Servlet response already use stream, Writer not possible
error when I do that. -
5. Re: how to download a file via Seam& JSF,
nickarls Jan 23, 2008 4:36 PM (in response to tyshan)Hmm, using a ServletOutputStream os shouldn't make a difference, should it? One one think that it's the same code called...
-
6. Re: how to download a file via Seam& JSF,
nickarls Jan 23, 2008 4:45 PM (in response to tyshan)Is FacesContext.getCurrentInstance().getResponseStream() useable?
-
7. Re: how to download a file via Seam& JSF,
dustismo Jan 23, 2008 6:04 PM (in response to tyshan)The code I posted works fine for me.. Here is a working example.
Component:@Name("testController") @Scope(ScopeType.PAGE) public class TestController { public void hello() { try { FacesContext context = FacesContext.getCurrentInstance(); HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse(); response.setContentType("text/plain"); //fill in contentType OutputStream os = response.getOutputStream(); os.write("HELLO THERE".getBytes()); //fill in bytes os.flush(); os.close(); context.responseComplete(); } catch (Exception x) { x.printStackTrace(); } } }
View:<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:s="http://jboss.com/products/seam/taglib" xmlns:ui="http://java.sun.com/jsf/facelets" template="templates/template.xhtml" > <s:button action="#{testController.hello}" value="test"/> </ui:composition>
-
8. Re: how to download a file via Seam& JSF,
squ1rr3l Jan 23, 2008 8:36 PM (in response to tyshan)Well I'm not sure why this isn't working for Jasper output, then. My code is very similar (although there is more involved, of course). I was actually getting the context before using injection, which worked better. I'm also using a session EJB - I assume your test code is not.
In any case, usingFacesContext context = FacesContext.getCurrentInstance();
causes errors even earlier. When I doHttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
I get an exception:20:00:28,098 ERROR [STDERR] java.lang.IllegalStateException 20:00:28,108 ERROR [STDERR] at com.sun.faces.context.FacesContextImpl.assertNotReleased(FacesContextImpl.java:428) 20:00:28,108 ERROR [STDERR] at com.sun.faces.context.FacesContextImpl.getExternalContext(FacesContextImpl.java:149) 20:00:28,108 ERROR [STDERR] at org.my.project.session.I9CertForm.generateCertificate(I9CertForm.java:145)
-
9. Re: how to download a file via Seam& JSF,
squ1rr3l Jan 23, 2008 10:04 PM (in response to tyshan)Ok, I have my code working now. There were a couple of things that didn't work:
1) Initially I tried using theJasperExportManager.exportReportToPdfStream(jasperPrint, outputStream);
for passing the outputStream from the Response object to the JasperExportManager. AFAIK, that's what produced the "Writer not possible" error.
2) In the session EJB, using FacesContext.getCurrentInstance() does not provide a usable context - at least not one that can be used to obtain the Response object. So maybe that's usable in a POJO component, but not an EJB component, and that's possibly by design, I don't know. Scope doesn't really seem to matter.
Anyway, what works is this:
- In the session EJB:@In private FacesContext facesContext; private byte[] report1; ... String reportName = "/reports/myreport.jrxml"; CreateReport cr = new CreateReport(); report2 = cr.getReport(reportName); try { HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse(); response.setContentType("application/pdf"); OutputStream os = response.getOutputStream(); os.write(report2); os.flush(); os.close(); facesContext.responseComplete(); } catch(Exception ex) { ex.printStackTrace(); }
Just for completeness - the CreateReport.getReport method just does the jasper stuff to load and fill the report, then return the byte array:public byte[] getReport(String reportName) { try { ServletContext sCtxt = ServletLifecycle.getServletContext(); File reportFile = new File(sCtxt.getRealPath(reportName)); if( !reportFile.exists()) { throw new JRRuntimeException("File " + reportName + " not found."); } JasperDesign jasperDesign = JRXmlLoader.load(reportFile); JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign); JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, conn); if (jasperPrint != null) { byte[] reportPDF = JasperExportManager.exportReportToPdf(jasperPrint); return reportPDF; } else { throw new JRRuntimeException("null jasperPrint"); return null; } } catch (Exception e) { e.printStackTrace(); } return null; }
Thanks for the help! -
10. Re: how to download a file via Seam& JSF,
tynor Jan 30, 2008 12:08 PM (in response to tyshan)Our application uses the same technique as discussed in this thread for downloading files (see below).
This works, but if any messages (FacesMessage) are queued during the generation of the downloaded content, they are not displayed to the user since the facesContext.responseComplete() interrups the JSF lifecycle and the view is never rerendered.
Is there a way to generate downloadable content, as below, but still refresh the browser view, showing any pending messages? In many cases, we wish to provide downloadable content, but also include warning messages (e.g., "Warning: generated report includes partially validated records").
Thanks!HttpServletResponse response = (HttpServletResponse)facesContext.getExternalContext().getResponse(); try { response.setContentType(contentType); response.setHeader( "Content-Disposition", "attachment; filename=\"" + name + "\";"); response.getOutputStream().write(fileData); response.setStatus(HttpServletResponse.SC_OK); response.getOutputStream().close(); facesContext.responseComplete(); } catch (IOException ex) { log.error("Error writing file data (#0 bytes) to response", ex, fileData.length); }