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.
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:
-
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é. -
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 pourmode="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. -
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 parajax="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:
-
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 appelantgetParameter()
,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 dansweb.xml
. Si la requête n'est pas une requêtemultipart/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 -
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é unRequestDispatcher#forward()
appeler. Habituellement, les filtres de réécriture D'URL tels que PrettyFaces le font. Cela déclenche le répartiteurFORWARD
, mais les filtres écoutent par défaut sur le répartiteurREQUEST
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>
-
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 formulaireenctype
. 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 .
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>
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>
ressemble à javax.face.SÉPARATEUR_CHAR ne doit pas être égal à _
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
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>
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>
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.