web-dev-qa-db-fra.com

Comment envoyer l'octet [] au format PDF au navigateur dans Java?

Dans la méthode d'action (JSF), j'ai quelque chose comme ci-dessous:

public String getFile() {
  byte[] pdfData = ...
  // how to return byte[] as file to web browser user ?
}

Comment envoyer l'octet [] en pdf au navigateur?

18
marioosh

Dans la méthode d'action, vous pouvez obtenir la réponse du servlet HTTP sous les hottes JSF par ExternalContext#getResponse() . Ensuite, vous devez définir au moins l'en-tête HTTP Content-Type Sur application/pdf Et l'en-tête HTTP Content-Disposition Sur attachment (lorsque vous souhaitez insérer un Enregistrer sous dialogue) ou dans inline (lorsque vous souhaitez laisser le navigateur Web gérer l'affichage lui-même). Enfin, vous devez vous assurer d'appeler FacesContext#responseComplete() par la suite pour éviter que IllegalStateExceptions ne vole autour.

Exemple de lancement:

public void download() throws IOException {
    // Prepare.
    byte[] pdfData = getItSomehow();
    FacesContext facesContext = FacesContext.getCurrentInstance();
    ExternalContext externalContext = facesContext.getExternalContext();
    HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();

    // Initialize response.
    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("application/pdf"); // Check http://www.iana.org/assignments/media-types for all types. Use if necessary ServletContext#getMimeType() for auto-detection based on filename.
    response.setHeader("Content-disposition", "attachment; filename=\"name.pdf\""); // The Save As popup magic is done here. You can give it any filename you want, this only won't work in MSIE, it will use current request URL as filename instead.

    // Write file to response.
    OutputStream output = response.getOutputStream();
    output.write(pdfData);
    output.close();

    // Inform JSF to not take the response in hands.
    facesContext.responseComplete(); // Important! Else JSF will attempt to render the response which obviously will fail since it's already written with a file and closed.
}

Cela dit, si vous avez la possibilité d'obtenir le contenu PDF en tant que InputStream plutôt que byte[], Je recommanderais de l'utiliser à la place pour enregistrer le webapp à partir de porcs mémoire. Il vous suffit ensuite de l'écrire dans la boucle InputStream-OutputStream habituelle Java IO = chemin.

53
BalusC

Il vous suffit de définir le type mime sur application/x-pdf Dans votre réponse. Vous pouvez utiliser la méthode setContentType (String contentType) pour ce faire dans le cas du servlet.
Dans JSF/JSP, vous pouvez l'utiliser avant d'écrire votre réponse:

<%@ page contentType="application/x-pdf" %>

et response.write(yourPDFDataAsBytes()); pour écrire vos données.
Mais je vous conseille vraiment d'utiliser des servlets dans ce cas. JSF est utilisé pour rendre les vues HTML, pas PDF ou fichiers binaires.

Avec les servlets, vous pouvez utiliser ceci:

public MyPdfServlet extends HttpServlet {
    protected doGet(HttpServletRequest req, HttpServletResponse resp){
         OutputStream os = resp.getOutputStream();
         resp.setContentType("Application/x-pdf");
         os.write(yourMethodToGetPdfAsByteArray());
    } 
}

Ressources:

5
Colin Hebert

Lors de l'envoi de données brutes au navigateur à l'aide de JSF, vous devez extraire le HttpServletResponse du FacesContext.

À l'aide de HttpServletResponse, vous pouvez envoyer des données brutes au navigateur à l'aide de l'API standard IO.

Voici un exemple de code:

public String getFile() {
    byte[] pdfData = ...

    FacesContext context = FacesContext.getCurrentInstance();
    HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
    OutputStream out = response.getOutputStream();
    // Send data to out (ie, out.write(pdfData)).
}

En outre, voici d'autres éléments que vous voudrez peut-être envisager:

  • Définissez le type de contenu dans HttpServletResponse pour informer le navigateur que vous envoyez PDF data: response.setContentType ("application/pdf");
  • Informez le FacesContext que vous avez envoyé des données directement à l'utilisateur, à l'aide de la méthode context.responseComplete (). Cela empêche JSF d'effectuer un traitement supplémentaire inutile.
1
Vivien Barousse