web-dev-qa-db-fra.com

Téléchargement de fichiers JSF 2.0

Je regarde autour de quelques blogs, pour essayer de trouver comment télécharger des fichiers en utilisant JSF 2.0 Mais toutes les solutions me confondent. Je voudrais savoir de quoi ai-je besoin exactement pour pouvoir télécharger avec succès un fichier (MP3, PDF, vidéo ... quel que soit le type) et le stocker dans une base de données en tant que @Lob. Voici ce que j'ai fait jusqu'à présent:

  • J'ai créé une entité qui a un attribut de type octet [] et il est également annoté avec une annotation @Lob.

  • J'ai créé un EJB qui introduira l'entité avec une méthode qui a un octet [] comme paramètre et l'insère dans la base de données en utilisant la classe EntityManager (méthode persist).

  • J'ai créé une page JSF avec une balise d'entrée de type "fichier" et un bouton d'envoi

  • J'ai préparé un bean géré pour échanger des informations sur le fichier avec la page JSF.

Maintenant, je suis coincé et j'ai beaucoup de doutes:

  • Que dois-je faire pour passer le fichier du JSF au bean géré puis le transformer en octet [] (pour pouvoir le gérer vers l'EJB)?

  • Comment un servlet peut-il m'aider?

  • Ai-je besoin d'une servlet pour ce faire?

  • J'ai également constaté que dans certains blogs, il mentionne quelque chose à propos des servlets 3.0, mais je ne sais pas si mon environnement de travail l'utilise, comment le faire si j'utilise des servlets 3.0 (j'utilise JEE6)?

Je n'ai jamais téléchargé de fichier auparavant et je ne connais pas très bien les servlets. Je suis confus, quelqu'un pourrait me donner quelques conseils de départ, s'il vous plaît?

33
sfrj

Tout d'abord, cette (ancienne) question et réponse suppose JSF 2.0/2.1. Depuis JSF 2.2, il existe un <h:inputFile> composant sans avoir besoin de bibliothèques de composants tiers. Voir aussi Comment télécharger un fichier à l'aide de JSF 2.2 <h: inputFile>? Où est le fichier enregistré?


La manière la plus simple serait d'utiliser Tomahawk pour JSF 2. . Il offre un <t:inputFileUpload> composant.

Voici un didacticiel étape par étape:

  • Créez un projet Web dynamique vierge pour Servlet 3.0 et JSF 2.0. Le web.xml doit être conforme à la spécification Servlet 3.0 et contient déjà le servlet JSF:

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app 
        xmlns="http://Java.Sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:schemaLocation="http://Java.Sun.com/xml/ns/javaee http://Java.Sun.com/xml/ns/javaee/web-app_3_0.xsd"
        id="YourProjectName" version="3.0">
    
        <display-name>Your Project Name</display-name>
    
        <servlet>
            <servlet-name>Faces Servlet</servlet-name>
            <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>Faces Servlet</servlet-name>
            <url-pattern>*.xhtml</url-pattern>
        </servlet-mapping>
    
    </web-app>
    

    Le faces-config.xml doit être conforme aux spécifications JSF 2.0:

    <?xml version="1.0" encoding="UTF-8"?>
    <faces-config
        xmlns="http://Java.Sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://Java.Sun.com/xml/ns/javaee http://Java.Sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
        version="2.0">
    
    </faces-config>
    

  • Télécharger Tomahawk 1.1.10 pour JSF 2. . Extrayez le fichier Zip, accédez au /lib dossier et copiez tout *.jar fichiers dans votre /WEB-INF/lib.

    Il s'agit de 18 fichiers, dont batik*.jar et xml*.jar ne sont pas nécessaires pour utiliser seul le t:inputFileUpload composant. Vous pourriez les laisser de côté.


  • Configurez le filtre d'extensions Tomahawk dans web.xml. C'est celui qui est responsable de la gestion multipart/form-data requêtes requises pour pouvoir envoyer des fichiers via HTTP.

    <filter>
        <filter-name>MyFacesExtensionsFilter</filter-name>
        <filter-class>org.Apache.myfaces.webapp.filter.ExtensionsFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>MyFacesExtensionsFilter</filter-name>
        <servlet-name>Faces Servlet</servlet-name>
    </filter-mapping>
    

    Notez que le <servlet-name> doit correspondre exactement à <servlet-name> du FacesServlet comme vous l'avez défini dans web.xml.


  • Créez un simple Facelet, upload.xhtml:

    <!DOCTYPE html>
    <html lang="en"
        xmlns="http://www.w3.org/1999/xhtml"
        xmlns:f="http://Java.Sun.com/jsf/core"
        xmlns:h="http://Java.Sun.com/jsf/html"
        xmlns:t="http://myfaces.Apache.org/tomahawk"
        xmlns:ui="http://Java.Sun.com/jsf/facelets">
        <h:head>
            <title>Tomahawk file upload demo</title>
        </h:head>
        <h:body>
            <h:form enctype="multipart/form-data">
                <t:inputFileUpload value="#{bean.uploadedFile}" />
                <h:commandButton value="submit" action="#{bean.submit}" />
                <h:messages />
            </h:form>
        </h:body> 
    </html>
    

    Noter la enctype="multipart/form-data" attribut sur <h:form>, c'est très important pour pouvoir envoyer des fichiers avec HTTP.


  • Créez un bean géré simple, com.example.Bean:

    package com.example;
    
    import Java.io.IOException;
    
    import javax.faces.application.FacesMessage;
    import javax.faces.bean.ManagedBean;
    import javax.faces.bean.RequestScoped;
    import javax.faces.context.FacesContext;
    
    import org.Apache.commons.io.FilenameUtils;
    import org.Apache.myfaces.custom.fileupload.UploadedFile;
    
    @ManagedBean
    @RequestScoped
    public class Bean {
    
        private UploadedFile uploadedFile;
    
        public void submit() throws IOException {
            String fileName = FilenameUtils.getName(uploadedFile.getName());
            String contentType = uploadedFile.getContentType();
            byte[] bytes = uploadedFile.getBytes();
    
            // Now you can save bytes in DB (and also content type?)
    
            FacesContext.getCurrentInstance().addMessage(null, 
                new FacesMessage(String.format("File '%s' of type '%s' successfully uploaded!", fileName, contentType)));
        }
    
        public UploadedFile getUploadedFile() {
            return uploadedFile;
        }
    
        public void setUploadedFile(UploadedFile uploadedFile) {
            this.uploadedFile = uploadedFile;
        }
    
    }
    

Ça devrait être ça. Ouvrez-le par http: // localhost: 8080/projectname/upload.xhtml .

Quant à vos questions concrètes:

que dois-je faire pour passer le fichier du JSF au bean géré puis le transformer en octet [] (pour pouvoir le gérer vers l'EJB)?

Ceci est répondu ci-dessus.

Comment une servlet peut-elle m'aider?

Il est capable de traiter et de contrôler les requêtes/réponses HTTP. Dans un environnement JSF, le FacesServlet fait déjà tout le travail.

Ai-je besoin d'une servlet pour ce faire?

Dans un environnement JSF, le FacesServlet est obligatoire. Mais il est déjà fourni par l'API, vous n'avez pas besoin d'en écrire un vous-même. Cependant, pour pouvoir télécharger des fichiers à partir d'une base de données, une autre servlet est certainement utile. Vous pouvez trouver un exemple de base ici: Servlet pour servir du contenu statique .

J'ai également constaté que dans certains blogs, il mentionne quelque chose à propos des servlets 3.0, mais je ne sais pas si mon environnement de travail l'utilise, comment le faire si j'utilise des servlets 3.0 (j'utilise JEE6)?

Si vous utilisez un conteneur Servlet 3.0 comme Glassfish 3, JBoss AS 6, Tomcat 7, etc. et le web.xml est déclaré Servlet 3.0, alors vous utilisez certainement Servlet 3.0. Servlet 3.0 fait partie de Java EE 6.

70
BalusC

Pour être complet, je veux juste fournir un exemple entièrement fonctionnel autonome de la façon dont cela est fait avec JSF 2.2, soit avec des requêtes non Ajax et Ajax . Gardez à l'esprit que JSF 2.2 utilise différents espaces de noms et vous devez travailler avec un conteneur Servlet 3. (comme Tomcat 7.0.x, JBoss AS 6.x et 7.x et GlassFish 3.x).

fileUpload.xhtml

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head />
<h:body>
    <h:form enctype="multipart/form-data">
        <h:inputFile value="#{uploadBean.file}" />
        <h:commandButton value="Post Upload" action="#{uploadBean.upload}" />
    </h:form>
    <h:form enctype="multipart/form-data">
        <h:inputFile value="#{uploadBean.file}" />
        <h:commandButton value="Ajax Upload">
            <f:ajax listener="#{uploadBean.upload}" execute="@form"
                render="countOutput" />
        </h:commandButton>
    <!-- Counts the uploaded items -->
    <h:outputText id="countOutput"
        value="Files uploaded #{uploadBean.filesUploaded}" />
    </h:form>
</h:body>
</html>

UploadBean.Java:

@ManagedBean
@ViewScoped
public class UploadBean {

    private int filesUploaded = 0;

    //javax.servlet.http.Part (Servlet 3.0 API)
    private Part file;
    private String fileContent;

    /**
     * Just prints out file content
     */
    public void upload() {
        try {
            fileContent = new Scanner(file.getInputStream())
                    .useDelimiter("\\A").next();
            System.out.println(fileContent + " uploaded");
            filesUploaded++;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public int getFilesUploaded() {
        return filesUploaded;
    }

    public Part getFile() {
        return file;
    }

    public void setFile(Part file) {
        this.file = file;
    }
}

Voir aussi:

8
Xtreme Biker

Je recommanderais d'utiliser une bibliothèque complémentaire comme Tomahawk's <t:inputFileUpload> ou PrimeFaces <p:fileUpload> .

BalusC a également un joli blog sur Téléchargement de fichiers avec JSF 2.0 et Servlet 3.0.

3
Mark

Article de blog de BalusC: Téléchargement de fichiers avec JSF 2.0 et Servlet 3. est ce qui m'a sauvé, car j'ai eu des problèmes lors de l'exécution de la balise fileUpload de RichFaces 4 avec Spring WebFlow.

Il vaut la peine de modifier le code de BalusC pour utiliser le MultipartResolver de Spring - vous n'avez pas besoin de son MultipartMap de n autre article de blog .

Je l'ai atteint en modifiant une méthode decode dans FileRenderer comme ceci:

    UploadedFile ret = null;

    Object req = context.getExternalContext().getRequest();
    if (req instanceof MultipartHttpServletRequest) {
      MultipartFile file = ((MultipartHttpServletRequest)req).getFile(clientId);

      File temp = null;
      try {
        temp = File.createTempFile("_UPLOAD_", null);
        file.transferTo(temp);

        String name = new File(file.getOriginalFilename()).getName();
        ret = new UploadedFile(temp, name);

      } catch (IOException e) {
        throw new RuntimeException("Could not create temp file.", e);
      }
    } else {
      throw new IllegalStateException("Request is not multipart. Use spring's multipart resolver.");
    }
    // If no file is specified, set empty String to trigger validators.
    ((UIInput) component).setSubmittedValue( ret == null ? EMPTY_STRING : ret);

Un UploadedFile est un simple POJO sérialisable utilisé pour renvoyer les résultats au bean de sauvegarde.

2
Maciek Łoziński

Dans JSF 2.2, vous pouvez facilement télécharger un fichier à l'aide d'une balise sans utiliser de commons-io ou de filtre. Cette balise prend en charge les processus normal et ajax.

Normal:

    <h:inputFile id="file"  value="#{fileUploadBean.uploadedFile}"/> 
    <h:commandButton id="button" action="#{fileUploadBean.sumbit()}" value="Upload"/>

Ajax:

    <h:inputFile id="file" value="#{fileUploadBean.uploadedFile}"/> 
    <h:commandButton id="button" value="submit">
      <f:ajax execute="@all" render="@all" onevent="statusUpdate"/>
    </h:commandButton>

Concevez votre bean géré comme suit:

  @Named
  @RequestScoped
  public class FileUploadBean {

   private Part uploadedFile;

  }
2
Masudul

Vous devez ajouter commons-fileupload-1.2.1.jar dans notre projet Build Path

1.Configurez le fichier web.xml:

Web.xml

    <filter>
        <filter-name>PrimeFaces FileUpload Filter</filter-name>
        <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>PrimeFaces FileUpload Filter</filter-name>
        <servlet-name>Faces Servlet</servlet-name>
    </filter-mapping>
    <mime-mapping>        
        <extension>png</extension>
        <mime-type>image/png</mime-type>
    </mime-mapping>

2. Créer ManagedBean

   @ManagedBean
   @SessionScoped
public class FileUploadBean implements Serializable{
public FileUpload (){
}
  private StreamedContent file;
public void loadFile(FileUploadEvent event) throws IOException, InterruptedException {

        InputStream input = new ByteArrayInputStream(event.getFile().getContents());
        file= new DefaultStreamedContent(input, "image/jpg");
    }
}

Fichier 3.jsf (xhtml)

   <h:form enctype="multipart/form-data"> 
         <p:fileUpload fileUploadListener="#{fileUploadBean.file}" sizeLimit="100000" allowTypes="/(\.|\/)(gif|jpe?g|png|bmp)$/"/>
        </h:form>
0
user2354035

La façon la plus simple est probablement d'utiliser la balise inputFileUpload que vous pouvez trouver dans MyFaces:

http://myfaces.Apache.org/

0
Vladimir Ivanov

IceFaces2.0 en a un, http://wiki.icefaces.org/display/ICE/FileEntry Je n'ai pas encore essayé de l'implémenter, mais le téléchargement a des exemples d'applications et il fonctionne sous Tomcat 6 (servlet 2.5, donc pas JEE6)

0
JimO