3 Replies Latest reply on Dec 6, 2008 9:35 PM by Ken Clark

    Downloading a file based on user input fields

    Ken Clark Newbie

      I am trying to get a page working that has some user provided input fields, and a button (or link) which will build an XML file for the user based on the inputs and send back the XML file.


      I implemented the XML generation as:



      FacesContext context = FacesContext.getCurrentInstance();
      HttpServletResponse response = (HttpServletResponse) context.
          getExternalContext().getResponse();
      response.setHeader("Content-Type", "application/xml");
      response.setContentLength(xml.length());
      
      ServletOutputStream out;
      try
      {
          out = response.getOutputStream();
          out.println(xml);
          out.flush();
          out.close();
          return null;
      }
      catch (Exception e)
      {
          return handleException(e);
      }
      finally
      {
          context.responseComplete();
      }
      



      This works fine when I use s:link to execute the action class method, but when I do it this way, the fields in the form do not get injected.


      When I use h:commandButton, the fields are injected as expected, but now the redirection of the output does not work (no file is downloaded.)


      Is there any happy medium wherein I can get both functionalities as I need them?


      Thanks
      ken

        • 1. Re: Downloading a file based on user input fields
          Adrian Mitev Master


          This works fine when I use s:link to execute the action class method, but when I do it this way, the fields in the form do not get injected.

          This is because s:link does not submit the form.



          When I use h:commandButton, the fields are injected as expected, but now the redirection of the output does not work (no file is downloaded.)

          Try the following code:


          public String download() {
              HttpServletResponse response = (HttpServletResponse)extCtx.getResponse();
              response.setContentType("application/octet-stream");
              response.addHeader("Content-Disposition","attachment;filename=" + FILE_NAME);
              PrintWriter writer = response.getWriter();
          
              /* DO YOUR THING (like writer.write) */
          
              writer.flush();
              facesContext.responseComplete();
              writer.close();
          
              return "result;
          }
          



          And finally - for better code design used dependency injection for the faces context.


          @In FacesContext facesContext;
          




          • 2. Re: Downloading a file based on user input fields
            Ken Clark Newbie

            I won't be able to try this out until later today, but let me see if I understand the changes you suggest:


            1) Change from using OutputStream to using PrintWriter (it does not seem like this should change anything to me.)


            2) Change from return null to return result -- is there a corresponding navigation change that needs to be done for this?  Seems like it would not matter anyway since we are doing ctx.responseComplete().


            3) Slight change on when responseComplete is called -- this may change the way error processing proceeds it seems but would it affect my main problem?


            Sorry if I am being dense -- is there a difference other than these that I am missing?


            Thanks,
            ken

            • 3. Re: Downloading a file based on user input fields
              Ken Clark Newbie

              I tried this code...


              I got an error that getWriter() had already been called, so that did not work.


              I made the response.setHeader and addHeader changes but that had no effect.


              It just seems that on a post, the strategy of re-routing the response cannot work.  Is there any way to do this?


              Alternately, is there a way I could set up the pages.xml configuration in such a way that I can do this?


              Thanks,
              ken