2 Replies Latest reply on Nov 12, 2009 9:43 AM by bm97

    File Download link using a4j:commandLink

      Hello, I'm trying to create a file download link in my application, but I am having trouble. The scenario is as follows: There is a "file-explorer" like popup panel (using rich:modalPanel) which lists files in the server. When the user clicks on the file name, the contents of that file should be sent to the browser (opening the "Save As..." dialog).

      I am already able to get the file's contents in an InputStream. The code in the Facelets file which contains the filename-link looks like this:

      <a4j:commandLink ajaxSingle="false" immediate="true"
       value="#{item.name}"
       action="#{RepositoryBean.downloadResource}"
       rendered="#{! item.directory}">
       <f:setPropertyActionListener value="#{item}"
       target="#{RepositoryBean.clickedResource}" />
      </a4j:commandLink>
      


      ("item" is the object representing a downloadable resource on the server). The code in my RepositoryBean looks like this (edited a little):

      public String downloadResource() {
      
       InputStream content = ... // correctly gets the file's content
       String filename = ...
       String mimeType = "application/force-download";
      
       HttpServletResponse response = FacesContext.getCurrentInstance(....).getResponse();
      
       response.setContentType( mimeType );
       response.addHeader( "Content-Disposition", "attachment; filename=\"" + filename + "\"" );
      
       try {
       ServletOutputStream os = response.getOutputStream();
       IOUtils.copy( is, os ); // Apache Commons-IO
       os.close();
       os.flush();
       FacesContext.getCurrentInstance().responseComplete();
       } catch ( Exception exc ) {
       exc.printStackTrace();
       }
      
       return null;
      }
      


      Notice I have manually filled the Response object with the bytes I need, and also called responseComplete() so JSF doesn't try writing anything else in the response (was getting errors before this).

      Clicking the download link DOES trigger the action and DOES return the content to the browser, HOWEVER it always displays the byte content on the browser (even if it is a binary file, showing gibberish).

      I suppose the Javascript code that receives the response simply "pastes" it into the document somehow. Is there a way to tell it to download the stream instead?

      I was trying to do this with h:commandLink before, but ran into several problems, so I'd like to solve this with a4j:commandLink first. If it is not possible I'll post the problem with h:commandLink.

      Thanks in advance!