96 votes

Comment diffuser un téléchargement de fichier dans un bean de sauvegarde JSF?

Apache MyFaces Trinidad est la composante <tr:fileDownloadActionListener>. Je vais avoir pas de problèmes pour l'utiliser, comme il est décrit dans les docs. Est-il possible de simuler même comportement que cette balise à partir de la sauvegarde de haricot? J'ai essayé beaucoup de choses. Principal problème est que je ne peux pas obtenir de l' OutputStream de réponses (à simuler). J'ai créé Servlet qui créent même fichier en <tr:fileDownloadActionListener> mais ce servlet nécessite une nouvelle demande. Comment obtenir de l' OutputStream de courant en FacesContext?

262voto

BalusC Points 498232

Vous pouvez obtenir tout par ExternalContext. Dans JSF 1.x, vous pouvez obtenir le raw HttpServletResponse objet en ExternalContext#getResponse(). Dans JSF 2.x, vous pouvez utiliser le bouquet de nouveau délégué méthodes comme ExternalContext#getResponseOutputStream() sans avoir besoin de saisir l' HttpServletResponse sous le JSF hottes. Le plus important est de s'appellent FacesContext#responseComplete() d'informer JSF qu'il ne devrait pas effectuer de navigation et le rendu après que vous avez écrit sur le fichier pour la réponse, sinon la fin de la réponse va être polluée par le contenu HTML de la page.

Voici quelques éléments de base de lancement pour les exemples de la diffusion d'un fichier de demande de téléchargement.

JSF 1.x:

public void download() throws IOException {
    FacesContext fc = FacesContext.getCurrentInstance();
    HttpServletResponse response = (HttpServletResponse) fc.getExternalContext().getResponse();

    response.reset(); // Some JSF component library or some Filter might have set some headers in the buffer beforehand. We want to get rid of them, else it may collide.
    response.setContentType(contentType); // Check http://www.w3schools.com/media/media_mimeref.asp for all types. Use if necessary ServletContext#getMimeType() for auto-detection based on filename.
    response.setContentLength(contentLength); // Set it with the file size. This header is optional. It will work if it's omitted, but the download progress will be unknown.
    response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\""); // The Save As popup magic is done here. You can give it any file name you want, this only won't work in MSIE, it will use current request URL as file name instead.

    OutputStream output = response.getOutputStream();
    // Now you can write the InputStream of the file to the above OutputStream the usual way.
    // ...

    fc.responseComplete(); // Important! Otherwise JSF will attempt to render the response which obviously will fail since it's already written with a file and closed.
}

JSF 2.x:

public void download() throws IOException {
    FacesContext fc = FacesContext.getCurrentInstance();
    ExternalContext ec = fc.getExternalContext();

    ec.responseReset(); // Some JSF component library or some Filter might have set some headers in the buffer beforehand. We want to get rid of them, else it may collide.
    ec.setResponseContentType(contentType); // Check http://www.iana.org/assignments/media-types for all types. Use if necessary ExternalContext#getMimeType() for auto-detection based on filename.
    ec.setResponseContentLength(contentLength); // Set it with the file size. This header is optional. It will work if it's omitted, but the download progress will be unknown.
    ec.setResponseHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\""); // The Save As popup magic is done here. You can give it any file name you want, this only won't work in MSIE, it will use current request URL as file name instead.

    OutputStream output = ec.getResponseOutputStream();
    // Now you can write the InputStream of the file to the above OutputStream the usual way.
    // ...

    fc.responseComplete(); // Important! Otherwise JSF will attempt to render the response which obviously will fail since it's already written with a file and closed.
}

Vous avez seulement besoin de s'assurer que l'action de la méthode n'est pas appelée par une requête ajax, mais qu'il est appelé par une requête normale comme vous le feu avec de l' <h:commandLink> et <h:commandButton>. Les requêtes Ajax sont traitées par JavaScript qui à son tour a, pour des raisons de sécurité, pas d'installations pour forcer l' Enregistrer Comme un dialogue avec le contenu de la réponse ajax.

Si vous êtes en utilisant JSF bibliothèque utilitaire OmniFaces, alors vous pouvez utiliser l'un des trois commode Faces#sendFile() méthodes.

public void download() throws IOException {
    Faces.sendFile(file, true);
}

-3voto

Bharat Sharma Points 27

voici l'extrait de code complet http://bharatonjava.wordpress.com/2013/02/01/downloading-file-in-jsf-2/

  @ManagedBean(name = "formBean")
 @SessionScoped
 public class FormBean implements Serializable
 {
   private static final long serialVersionUID = 1L;

   /**
    * Download file.
    */
   public void downloadFile() throws IOException
   {
      File file = new File("C:\\docs\\instructions.txt");
      InputStream fis = new FileInputStream(file);
      byte[] buf = new byte[1024];
      int offset = 0;
      int numRead = 0;
      while ((offset < buf.length) && ((numRead = fis.read(buf, offset, buf.length -offset)) >= 0)) 
      {
        offset += numRead;
      }
      fis.close();
      HttpServletResponse response =
         (HttpServletResponse) FacesContext.getCurrentInstance()
        .getExternalContext().getResponse();

     response.setContentType("application/octet-stream");
     response.setHeader("Content-Disposition", "attachment;filename=instructions.txt");
     response.getOutputStream().write(buf);
     response.getOutputStream().flush();
     response.getOutputStream().close();
     FacesContext.getCurrentInstance().responseComplete();
   }
 }
 

Vous pouvez modifier la logique de lecture du fichier si vous souhaitez que le fichier soit généré au moment de l'exécution.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X