Comment utiliser PrimeFaces p: fileUpload? La méthode d'écoute n'est jamais invoquée ou le fichier téléchargé est null / envoie une erreur / non utilisable

j'essaie de télécharger un fichier en utilisant PrimeFaces, mais la méthode fileUploadListener n'est pas invoquée après la fin du téléchargement.

Voici la vue:

<h:form>
    <p:fileUpload fileUploadListener="#{fileUploadController.handleFileUpload}"
        mode="advanced" 
        update="messages"
        sizeLimit="100000" 
        allowTypes="/(.|/)(gif|jpe?g|png)$/"/>

    <p:growl id="messages" showDetail="true"/>
</h:form>

et le haricot:

@ManagedBean
@RequestScoped
public class FileUploadController {

    public void handleFileUpload(FileUploadEvent event) {
        FacesMessage msg = new FacesMessage("Succesful", event.getFile().getFileName() + " is uploaded.");
        FacesContext.getCurrentInstance().addMessage(null, msg);
    }

}

j'ai placé un point de rupture sur la méthode, mais il n'est jamais appelé. En utilisant mode="simple" et ajax="false" , il est invoqué, mais je veux qu'il fonctionne dans le mode avancé. J'utilise Netbeans et Glassfish 3.1.

92
demandé sur Kukeltje 2012-01-16 08:37:59

8 réponses

comment configurer et dépanner <p:fileUpload> dépend de la version de PrimeFaces.

toutes les versions de PrimeFaces

les prescriptions ci-après s'appliquent à toutes les versions de PrimeFaces:

  1. l'attribut enctype de <h:form> doit être défini à multipart/form-data . Lorsque ceci est absent, le téléchargement ajax peut juste fonctionner, mais le comportement général du navigateur n'est pas spécifié et dépend de la forme composition et webbrowser/version. Il suffit de toujours le spécifier pour être du bon côté.

  2. lorsque vous utilisez mode="advanced" (c.-à-d. Ajax upload, c'est la valeur par défaut), assurez-vous que vous avez un <h:head> dans le modèle (maître). Cela permettra d'assurer que les fichiers JavaScript sont inclus. Ceci n'est pas requis pour mode="simple" (Non-ajax upload), mais cela briserait le look et la fonctionnalité de tous les autres PrimeFaces composants, donc vous ne voulez pas manquer cela de toute façon.

  3. lorsque vous utilisez mode="simple" (c.-à-d. non-ajax upload), alors ajax doit être désactivé sur n'importe quels boutons/liens de commande PrimeFaces par ajax="false" , et vous devez utiliser <p:fileUpload value> avec <p:commandButton action> au lieu de <p:fileUpload fileUploadListener> .

ainsi, si vous voulez (auto) télécharger le fichier avec le soutien d'ajax (mind the <h:head> !):

<h:form enctype="multipart/form-data">
    <p:fileUpload fileUploadListener="#{bean.upload}" auto="true" />
</h:form>
public void upload(FileUploadEvent event) {
    UploadedFile uploadedFile = event.getFile();
    String fileName = uploadedFile.getFileName();
    String contentType = uploadedFile.getContentType();
    byte[] contents = uploadedFile.getContents(); // Or getInputStream()
    // ... Save it, now!
}

ou si vous voulez télécharger un fichier non-ajax:

<h:form enctype="multipart/form-data">
    <p:fileUpload mode="simple" value="#{bean.uploadedFile}" />
    <p:commandButton value="Upload" action="#{bean.upload}" ajax="false" />
</h:form>
private UploadedFile uploadedFile; // +getter+setter

public void upload() {
    String fileName = uploadedFile.getFileName();
    String contentType = uploadedFile.getContentType();
    byte[] contents = uploadedFile.getContents(); // Or getInputStream()
    // ... Save it, now!
}

notez que l'ajax liées à des attributs tels que auto , allowTypes , update , onstart , oncomplete , etc sont ignoré dans mode="simple" . Il est donc inutile de Les préciser dans un tel cas.

notez également que vous devez lire le contenu du fichier immédiatement à l'intérieur de la les méthodes mentionnées ci-dessus et non dans une méthode bean différente invoquée par une requête HTTP ultérieure. Ceci est dû au fait que le contenu du fichier téléchargé est une requête scopée et donc indisponible dans une requête HTTP ultérieure/différente. Toute tentative de le lire dans une demande ultérieure aboutira très probablement avec java.io.FileNotFoundException sur le fichier temporaire.


PrimeFaces 5.x

cela ne nécessite pas de configuration supplémentaire si vous utilisez JSF 2.2 et votre faces-config.xml est également déclaré conforme JSF version 2.2. Vous n'avez pas besoin du tout du filtre de téléchargement de fichier PrimeFaces. Si vous ne savez pas comment installer et configurer correctement JSF en fonction du serveur cible utilisé, passez à comment installer et configurer correctement les bibliothèques JSF via Maven? et section" Installer JSF "de notre page wiki JSF .

si vous n'utilisez pas encore JSF 2.2 et que vous ne pouvez pas le mettre à jour (devrait être sans effort lorsque déjà sur un conteneur compatible Servlet 3.0), alors vous devez enregistrer manuellement le filtre de téléchargement de fichier PrimeFaces ci-dessous dans web.xml (il analysera la requête multi-pièces et remplira la carte des paramètres de requête régulière afin que FacesServlet puisse continuer à fonctionner comme d'habitude):

<filter>
    <filter-name>primeFacesFileUploadFilter</filter-name>
    <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>primeFacesFileUploadFilter</filter-name>
    <servlet-name>facesServlet</servlet-name>
</filter-mapping>

la valeur de <servlet-name> de facesServlet doit correspondre exactement à la valeur de <servlet> de javax.faces.webapp.FacesServlet dans le même web.xml . Donc si c'est par exemple Faces Servlet , alors vous devez l'éditer en conséquence pour correspondre.


PrimeFaces 4.x

même histoire que PrimeFaces 5.x s'applique au 4.x ainsi.

il n'y a qu'un problème potentiel à obtenir le contenu du fichier téléchargé par UploadedFile#getContents() . Cela retournera null lorsque L'API native est utilisée à la place D'Apache Commons FileUpload. Vous devez utiliser UploadedFile#getInputStream() à la place. Voir aussi Comment insérer l'image téléchargée de p: fileUpload comme BLOB dans MySQL?

un autre problème potentiel avec L'API native se manifestera lorsque le composant de téléchargement est présent sous une forme sur laquelle une autre requête ajax" régulière " est lancée qui ne traite pas le composant de téléchargement. Voir aussi le téléchargement de fichier ne fonctionne pas avec AJAX dans PrimeFaces 4.0/JSF 2.2.x-javax.servlet.ServletException: la requête content-type n'est pas multipart / form-data .

ces deux problèmes peuvent également être résolus en passant à Apache Commons FileUpload. Voir PrimeFaces 3.x l'article pour plus de détails.


PrimeFaces 3.x

cette version ne supporte pas le téléchargement de fichiers natifs JSF 2.2 / Servlet 3.0. Vous devez installer manuellement Apache Commons FileUpload et enregistrer explicitement le filtre de téléchargement de fichier dans web.xml .

vous avez besoin des bibliothèques suivantes:

ceux-ci doivent être présents dans le webapp's runtime classpath. Lors de L'utilisation de Maven, assurez-vous qu'ils sont au moins exécutés (la portée par défaut de la compilation est également bonne). Lorsque vous transportez manuellement des pots, assurez-vous qu'ils se retrouvent dans le dossier /WEB-INF/lib .

le détail de l'enregistrement du filtre de téléchargement de fichier se trouve dans PrimeFaces 5.x l'article ci-dessus. Dans le cas où vous utilisez PrimeFaces 4+ et que vous souhaitez utiliser explicitement Apache Commons FileUpload au lieu de JSF 2.2 / Servlet 3.0 native file upload, alors vous avez besoin à côté des bibliothèques mentionnées et filtrer aussi le param de contexte ci-dessous dans web.xml :

<context-param>
    <param-name>primefaces.UPLOADER</param-name>
    <param-value>commons</param-value><!-- Allowed values: auto, native and commons. -->
</context-param>

dépannage

In si cela ne fonctionne toujours pas, voici une autre cause possible sans rapport avec la configuration de PrimeFaces:

  1. seulement si vous utilisez le filtre de téléchargement de fichier PrimeFaces: il y a un autre Filter dans votre webapp qui exécute avant le filtre de téléchargement de fichier PrimeFaces et a déjà consommé le corps de la requête en appelant getParameter() , getParameterMap() , getReader() , etcetera. Un corps de requête ne peut être analysé qu'une seule fois. Lorsque vous appelez l'une de ces méthodes avant que le filtre de téléchargement de fichier ne fasse son travail, alors le filtre de téléchargement de fichier obtiendra un corps de requête vide.

    pour corriger cela, vous devez mettre le <filter-mapping> du filtre de téléchargement de fichier avant l'autre filtre dans web.xml . Si la requête n'est pas une requête multipart/form-data , alors le filtre de téléchargement de fichier continuera comme si rien ne s'était passé. Si vous utilisez des filtres qui sont automatiquement ajoutés parce qu'ils utilisez les annotations (par exemple PrettyFaces), vous pourriez avoir besoin d'ajouter un ordre explicite via le web.XML. Voir Comment définir le filtre de servlet ordre d'exécution à l'aide d'annotations dans la GUERRE

  2. seulement si vous utilisez le filtre de téléchargement de fichier PrimeFaces: Il ya un autre Filter dans votre webapp qui exécute avant le filtre de téléchargement de fichier PrimeFaces et a effectué un RequestDispatcher#forward() appeler. Habituellement, les filtres de réécriture D'URL tels que PrettyFaces le font. Cela déclenche le répartiteur FORWARD , mais les filtres écoutent par défaut sur le répartiteur REQUEST seulement.

    pour corriger cela, vous devez soit mettre le filtre de téléchargement de fichier PrimeFaces avant le filtre de redirection, ou pour reconfigurer le filtre de téléchargement de fichier PrimeFaces pour écouter sur FORWARD répartiteur trop:

    <filter-mapping>
        <filter-name>primeFacesFileUploadFilter</filter-name>
        <servlet-name>facesServlet</servlet-name>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>
    
  3. il y a un <h:form> emboîté . Ceci est illégal en HTML et le comportement du navigateur n'est pas spécifié. Le plus souvent, le navigateur n'envoie pas les données attendues sur "soumettre". Assurez-vous que vous ne nichez pas <h:form> . Ceci est complètement indépendamment du formulaire enctype . Il suffit de ne pas nid formes du tout.

si vous avez encore des problèmes, déboguez le trafic HTTP. Ouvrir le navigateur internet du développeur ensemble d'outils (appuyez sur F12 dans Chrome / Firebug23+ / IE9+) et vérifiez la section Net/Network. Si la partie HTTP semble correcte, déboguez le code JSF. Mettez un point d'arrêt sur FileUploadRenderer#decode() et avancez de là.


sauvegarde de fichier téléchargé

après que vous l'ayez finalement fait fonctionner, votre prochaine question sera probablement comme "Comment / où puis-je sauvegarder le fichier téléchargé?". Bien, continuez ici: comment sauver fichier téléchargé dans JSF .

193
répondu BalusC 2017-11-29 15:48:01

vous utilisez aussi des prettyfaces? Ensuite, réglez le répartiteur à l'avenir:

<filter-mapping>
   <filter-name>PrimeFaces FileUpload Filter</filter-name>
   <servlet-name>Faces Servlet</servlet-name>
   <dispatcher>FORWARD</dispatcher>
</filter-mapping>
30
répondu Reinaldo Gil 2012-01-31 20:06:17

un point que j'ai remarqué avec Primefaces 3.4 et Netbeans 7.2:

supprimer les paramètres Auto-remplis de Netbeans pour la fonction handleFileUpload i.e. (event) sinon l'événement pourrait être nul.

<h:form>
    <p:fileUpload fileUploadListener="#{fileUploadController.handleFileUpload(event)}"
        mode="advanced" 
        update="messages"
        sizeLimit="100000" 
        allowTypes="/(\.|\/)(gif|jpe?g|png)$/"/>

    <p:growl id="messages" showDetail="true"/>
</h:form>
6
répondu 2012-11-01 14:29:33

ressemble à javax.face.SÉPARATEUR_CHAR ne doit pas être égal à _

2
répondu HazeHorizon 2014-02-28 16:46:43

j'ai eu le même problème avec primefaces 5.3 et j'ai passé en revue tous les points décrits par BalusC sans résultat. J'ai suivi son Conseil de déboguer FileUploadRenderer#decode() et j'ai découvert que mon web.xml a été mal défini

<context-param>
  <param-name>primefaces.UPLOADER</param-name>
  <param-value>auto|native|commons</param-value>
</context-param>

la valeur param doit être 1 de ces 3 valeurs mais pas toutes!! toute la section context-param peut être supprimée et la valeur par défaut sera auto

0
répondu eric A 2017-01-05 13:20:18

bean.XHTML

    <h:form enctype="multipart/form-data">    
<p:outputLabel value="Choose your file" for="submissionFile" />
                <p:fileUpload id="submissionFile"
                    value="#{bean.file}"
                    fileUploadListener="#{bean.uploadFile}" mode="advanced"
                    auto="true" dragDropSupport="false" update="messages"
                    sizeLimit="100000" fileLimit="1" allowTypes="/(\.|\/)(pdf)$/" />

</h:form>

Bean.java

@ManagedBean

@ViewScoped public class Submission implements Serialisable {

private UploadedFile file;

//Gets
//Sets

public void uploadFasta(FileUploadEvent event) throws FileNotFoundException, IOException, InterruptedException {

    String content = IOUtils.toString(event.getFile().getInputstream(), "UTF-8");

    String filePath = PATH + "resources/submissions/" + nameOfMyFile + ".pdf";

    MyFileWriter.writeFile(filePath, content);

    FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO,
            event.getFile().getFileName() + " is uploaded.", null);
    FacesContext.getCurrentInstance().addMessage(null, message);

}

}

web.xml

    <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<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>
0
répondu Waldeyr Mendes da Silva 2017-05-16 12:29:10

aucune de ces suggestions ne m'a été utile. J'ai donc dû déboguer primefaces et j'ai trouvé que la raison du problème était:

java.lang.IllegalStateException: No multipart config for servlet fileUpload

puis j'ai ajouté la section dans Mes faces servlet dans le web.XML. Cela a donc résolu le problème:

<servlet>
    <servlet-name>main</servlet-name>

        <servlet-class>org.apache.myfaces.webapp.MyFacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
        <multipart-config>
            <location>/tmp</location>
            <max-file-size>20848820</max-file-size>
            <max-request-size>418018841</max-request-size>
            <file-size-threshold>1048576</file-size-threshold>
        </multipart-config>
    </servlet>
0
répondu engilyin 2017-07-28 12:17:09

j'ai eu le même problème, en raison du fait que j'avais toute la configuration qui décrit dans ce post, mais dans mon cas était parce que j'avais deux importations jquery (l'un d'eux était la requête de primefaces) qui a provoqué des conflits pour télécharger des fichiers.

Voir Primefaces conflits Jquery

0
répondu Christian Altamirano Ayala 2017-10-05 20:21:35