La configuration et le dépannage <p:fileUpload>
dépendent de la version de PrimeFaces.
Toutes les versions de PrimeFaces
Les exigences ci-dessous s'appliquent à toutes les versions de PrimeFaces:
L' enctype
attribut de <h:form>
doit être défini sur multipart/form-data
. Lorsque cela est absent, le téléchargement ajax peut simplement fonctionner, mais le comportement général du navigateur n'est pas spécifié et dépend de la composition du formulaire et de la création / version du navigateur Web. Précisez-le toujours pour être sûr.
Lorsque vous utilisez mode="advanced"
(c'est-à-dire le téléchargement ajax, c'est la valeur par défaut), assurez-vous que vous avez un <h:head>
dans le modèle (maître). Cela garantira que les fichiers JavaScript nécessaires sont correctement inclus. Ce n'est pas nécessaire pour le mode="simple"
(téléchargement non ajax), mais cela briserait l'apparence et la fonctionnalité de tous les autres composants PrimeFaces, vous ne voulez donc pas manquer cela de toute façon.
Lors de l'utilisation mode="simple"
(c.-à-d. Téléchargement non ajax), alors ajax doit être désactivé sur tous les 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>
(pour PrimeFaces <= 7.x) ou <p:fileUpload listener>
(pour PrimeFaces> = 8.x)
Donc, si vous voulez un téléchargement (automatique) de fichiers avec le support ajax (attention <h:head>
!):
<h:form enctype="multipart/form-data">
<p:fileUpload fileUploadListener="#{bean.upload}" auto="true" /> // for PrimeFaces >= 8.x this should be listener instead of fileUploadListener
</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 souhaitez 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 la attributs liés ajax tels que auto
, allowTypes
, update
, onstart
, oncomplete
, etc sont ignorés dans mode="simple"
. Il est donc inutile de les préciser dans ce cas.
Notez également que vous devez lire le contenu du fichier immédiatement à l'intérieur des méthodes susmentionnées et non dans une méthode de bean différente appelée par une requête HTTP ultérieure. Ceci est dû au fait que le contenu du fichier téléchargé est limité à la demande et donc indisponible dans une requête HTTP ultérieure / différente. Toute tentative de lecture dans une demande ultérieure aboutira probablement java.io.FileNotFoundException
sur le fichier temporaire.
PrimeFaces 8.x
La configuration est identique aux informations de version 5.x ci-dessous, mais si votre auditeur n'est pas appelé, vérifiez si l'attriubute est appelé listener
et non (comme avec les versions antérieures à 8.x)fileUploadListener
PrimeFaces 5.x
Cela ne nécessite aucune configuration supplémentaire si vous utilisez JSF 2.2 et que votre version JSF 2.2 faces-config.xml
est également déclarée conforme. Vous n'avez pas du tout besoin du filtre de téléchargement de fichiers PrimeFaces. Dans le cas où vous ne savez pas comment installer et configurer correctement JSF en fonction du serveur cible utilisé, dirigez-vous vers Comment installer et configurer correctement les bibliothèques JSF via Maven? et la section "Installer JSF" de notre page wiki JSF .
Cependant, si vous n'utilisez pas encore JSF 2.2 et que vous ne pouvez pas le mettre à niveau (cela devrait être sans effort lorsque vous êtes déjà sur un conteneur compatible Servlet 3.0), vous devez enregistrer manuellement le filtre de téléchargement de fichier PrimeFaces ci-dessous web.xml
(il analysera le multi demande de pièce et remplissez la carte des paramètres de la demande régulière afin que vous FacesServlet
puissiez continuer à travailler 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 <servlet-name>
valeur de facesServlet
doit correspondre exactement à la valeur de l' <servlet>
entrée du javax.faces.webapp.FacesServlet
dans le même web.xml
. Donc, si c'est par exemple Faces Servlet
, vous devez le modifier en conséquence pour qu'il corresponde.
PrimeFaces 4.x
La même histoire que PrimeFaces 5.x s'applique également à 4.x.
Il n'y a qu'un problème potentiel pour obtenir le contenu du fichier téléchargé par UploadedFile#getContents()
. Cela reviendra null
lorsque l'API native est utilisée à la place d'Apache Commons FileUpload. Vous devez utiliser à la UploadedFile#getInputStream()
place. Voir aussi Comment insérer une image téléchargée depuis p: fileUpload en tant que 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 demande ajax "régulière" différente est déclenchée qui ne traite pas le composant de téléchargement. Voir aussi Le téléchargement de fichiers ne fonctionne pas avec AJAX dans PrimeFaces 4.0 / JSF 2.2.x - javax.servlet.ServletException: Le type de contenu de la demande n'est pas un multipart / form-data .
Les deux problèmes peuvent également être résolus en passant à Apache Commons FileUpload. Voir la section PrimeFaces 3.x pour plus de détails.
PrimeFaces 3.x
Cette version ne prend pas en charge 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 fichiers dans web.xml
.
Vous avez besoin des bibliothèques suivantes:
Ceux-ci doivent être présents dans le chemin de classe d'exécution de l'application Web. Lorsque vous utilisez Maven, assurez-vous qu'ils ont au moins une portée d'exécution (la portée par défaut de la compilation est également bonne). Lorsque vous transportez manuellement des fichiers JAR, assurez-vous qu'ils se retrouvent dans un /WEB-INF/lib
dossier.
Le détail de l'enregistrement du filtre de téléchargement de fichiers peut être trouvé dans la section PrimeFaces 5.x ci-dessus. Dans le cas où vous utilisez PrimeFaces 4+ et que vous souhaitez utiliser explicitement Apache Commons FileUpload au lieu du téléchargement de fichier natif JSF 2.2 / Servlet 3.0, vous avez besoin à côté des bibliothèques mentionnées et filtrez également le paramètre 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
Au cas où cela ne fonctionnerait toujours pas, voici une autre cause possible sans rapport avec la configuration de PrimeFaces:
Seulement si vous utilisez le filtre de téléchargement de fichier PrimeFaces: Il y a une autre Filter
dans votre webapp qui fonctionne avant le filtre de téléchargement de fichier PrimeFaces et a déjà consommé le corps de la demande en appelant par exemple getParameter()
, getParameterMap()
, getReader()
, etc.. 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, le filtre de téléchargement de fichier obtiendra un corps de requête vide.
Pour résoudre ce problème, vous devez placer le <filter-mapping>
filtre de téléchargement de fichiers avant l'autre filtre web.xml
. Si la demande n'est pas une multipart/form-data
demande, le filtre de téléchargement de fichiers continuera simplement comme si de rien n'était. Si vous utilisez des filtres qui sont ajoutés automatiquement parce qu'ils utilisent des annotations (par exemple PrettyFaces), vous devrez peut-être ajouter un ordre explicite via web.xml. Voir Comment définir l'ordre d'exécution du filtre de servlet à l'aide d'annotations dans WAR
Uniquement si vous utilisez le filtre de téléchargement de fichiers PrimeFaces: il y en a un autre Filter
dans votre application Web qui s'exécute avant le filtre de téléchargement de fichiers PrimeFaces et a effectué un RequestDispatcher#forward()
appel. Habituellement, les filtres de réécriture d'URL tels que PrettyFaces le font. Cela déclenche le FORWARD
répartiteur, mais les filtres écoutent par défaut sur le REQUEST
répartiteur uniquement.
Pour résoudre ce problème, vous devez soit placer le filtre de téléchargement de fichiers PrimeFaces avant le filtre de transfert, soit reconfigurer le filtre de téléchargement de fichiers PrimeFaces pour écouter également sur le FORWARD
répartiteur:
<filter-mapping>
<filter-name>primeFacesFileUploadFilter</filter-name>
<servlet-name>facesServlet</servlet-name>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
Il y a un imbriqué <h:form>
. Ceci est illégal en HTML et le comportement du navigateur n'est pas spécifié. Plus que souvent, le navigateur n'enverra pas les données attendues lors de la soumission. Assurez-vous que vous n'emboitez pas <h:form>
. Ceci est complètement indépendant de la forme enctype
. N'emboitez pas du tout les formulaires.
Si vous rencontrez toujours des problèmes, déboguez le trafic HTTP. Ouvrez l'ensemble d'outils de développement du navigateur Web (appuyez sur F12 dans Chrome / Firebug23 + / IE9 +) et consultez la section Net / Network. Si la partie HTTP semble correcte, déboguez le code JSF. Mettez un point d'arrêt FileUploadRenderer#decode()
et avancez à partir de là.
Enregistrement du fichier téléchargé
Une fois que vous l'avez finalement fait fonctionner, votre prochaine question sera probablement comme "Comment / où enregistrer le fichier téléchargé?". Eh bien, continuez ici: Comment enregistrer le fichier téléchargé dans JSF .
web.xml
conformément au Guide de l'utilisateur PrimeFaces. L'avez-vous lu quand même? Cela n'expliquerait cependant pas pourquoimode="simple"
fonctionne pour vous.