La modalità di configurazione e risoluzione dei problemi <p:fileUpload>
dipende dalla versione di PrimeFaces.
Tutte le versioni di PrimeFaces
I seguenti requisiti si applicano a tutte le versioni di PrimeFaces:
L' enctype
attributo di <h:form>
deve essere impostato su multipart/form-data
. Quando questo è assente, il caricamento ajax potrebbe funzionare, ma il comportamento generale del browser non è specificato e dipende dalla composizione del modulo e dalla marca / versione del browser web. Basta sempre specificarlo per essere al sicuro.
Quando usi mode="advanced"
(es. Caricamento ajax, questo è il valore predefinito), assicurati di avere un <h:head>
nel modello (principale). Ciò garantirà che i file JavaScript necessari siano inclusi correttamente. Questo non è richiesto per mode="simple"
(caricamento non ajax), ma ciò interromperebbe l'aspetto e la funzionalità di tutti gli altri componenti PrimeFaces, quindi non vorrai perderlo comunque.
Quando si utilizza mode="simple"
(ad es. Caricamento non ajax), l'ajax deve essere disabilitato su qualsiasi pulsante / collegamento di comando PrimeFaces da ajax="false"
e è necessario utilizzare <p:fileUpload value>
con <p:commandButton action>
invece di <p:fileUpload fileUploadListener>
(per PrimeFaces <= 7.x) o <p:fileUpload listener>
(per PrimeFaces> = 8.x)
Quindi, se vuoi il caricamento (automatico) del file con il supporto ajax (attenzione <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!
}
Oppure, se desideri caricare file 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!
}
Fare nota che gli attributi Ajax-correlati, come auto
, allowTypes
, update
, onstart
, oncomplete
, ecc sono ignorati in mode="simple"
. Quindi è inutile specificarli in questo caso.
Notare inoltre che è necessario leggere il contenuto del file immediatamente all'interno dei metodi sopra menzionati e non in un metodo bean diverso richiamato da una successiva richiesta HTTP. Questo perché il contenuto del file caricato ha un ambito di richiesta e quindi non è disponibile in una richiesta HTTP successiva / diversa. Qualsiasi tentativo di leggerlo in una richiesta successiva molto probabilmente finirà java.io.FileNotFoundException
nel file temporaneo.
PrimeFaces 8.x
La configurazione è identica alle informazioni sulla versione 5.x di seguito, ma se il tuo ascoltatore non viene chiamato, controlla se l'attributo è chiamato listener
e non (come con le versioni precedenti alla 8.x)fileUploadListener
PrimeFaces 5.x
Questo non richiede alcuna configurazione aggiuntiva se stai usando JSF 2.2 e la tua versione faces-config.xml
è anche dichiarata conforme JSF 2.2. Non hai affatto bisogno del filtro di caricamento file PrimeFaces. Nel caso in cui non ti sia chiaro come installare e configurare correttamente JSF a seconda del server di destinazione utilizzato, vai a Come installare e configurare correttamente le librerie JSF tramite Maven? e la sezione "Installazione di JSF" della nostra pagina wiki JSF .
Se tuttavia non stai ancora utilizzando JSF 2.2 e non puoi aggiornarlo (dovrebbe essere facile quando sei già su un contenitore compatibile con Servlet 3.0), allora devi registrare manualmente il filtro di caricamento file PrimeFaces sotto web.xml
(analizzerà il multi richiesta di parte e riempire la mappa dei parametri della richiesta regolare in modo che FacesServlet
possa continuare a funzionare come al solito):
<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>
Il <servlet-name>
valore di facesServlet
deve corrispondere esattamente al valore <servlet>
nell'entrata dello javax.faces.webapp.FacesServlet
stesso web.xml
. Quindi, se è ad esempio Faces Servlet
, devi modificarlo di conseguenza in modo che corrisponda.
PrimeFaces 4.x
La stessa storia di PrimeFaces 5.x vale anche per 4.x.
C'è solo un potenziale problema nell'ottenere il contenuto del file caricato da UploadedFile#getContents()
. Questo verrà restituito null
quando viene utilizzata l'API nativa al posto di Apache Commons FileUpload. Devi usare UploadedFile#getInputStream()
invece. Vedi anche Come inserire un'immagine caricata da p: fileUpload come BLOB in MySQL?
Un altro potenziale problema con l'API nativa si manifesterà quando il componente di caricamento è presente in un modulo in cui viene attivata una richiesta ajax "normale" diversa che non elabora il componente di caricamento. Vedi anche Il caricamento di file non funziona con AJAX in PrimeFaces 4.0 / JSF 2.2.x - javax.servlet.ServletException: il tipo di contenuto della richiesta non è un multipart / form-data .
Entrambi i problemi possono essere risolti anche passando ad Apache Commons FileUpload. Vedere la sezione PrimeFaces 3.x per i dettagli.
PrimeFaces 3.x
Questa versione non supporta il caricamento di file nativi JSF 2.2 / Servlet 3.0. È necessario installare manualmente Apache Commons FileUpload e registrare esplicitamente il filtro di caricamento dei file in formatoweb.xml
.
Hai bisogno delle seguenti librerie:
Devono essere presenti nel classpath di runtime della webapp. Quando si utilizza Maven, assicurarsi che abbiano almeno l'ambito di runtime (anche l'ambito di compilazione predefinito è buono). Quando si trasportano manualmente i JAR, assicurarsi che finiscano in/WEB-INF/lib
cartella.
I dettagli di registrazione del filtro di caricamento file possono essere trovati nella sezione PrimeFaces 5.x qui sopra. Nel caso in cui si utilizzi PrimeFaces 4+ e si desideri utilizzare esplicitamente Apache Commons FileUpload invece del caricamento di file nativo JSF 2.2 / Servlet 3.0, è necessario accanto alle librerie menzionate e filtrare anche il parametro di contesto sottostante in web.xml
:
<context-param>
<param-name>primefaces.UPLOADER</param-name>
<param-value>commons</param-value><!-- Allowed values: auto, native and commons. -->
</context-param>
Risoluzione dei problemi
Nel caso in cui ancora non funzioni, ecco altre possibili cause non correlate alla configurazione di PrimeFaces:
Solo se si sta utilizzando il filtro di caricamento di file primefaces: C'è un altro Filter
nel vostro webapp che corre prima che il filtro di upload di file primefaces e ha già consumato il corpo della richiesta da parte ad esempio di chiamata getParameter()
, getParameterMap()
, getReader()
, eccetera. Il corpo di una richiesta può essere analizzato solo una volta. Quando chiami uno di questi metodi prima che il filtro di caricamento del file faccia il suo lavoro, il filtro di caricamento del file avrà un corpo della richiesta vuoto.
Per risolvere questo problema, è necessario inserire il <filter-mapping>
filtro di caricamento file prima dell'altro filtro in web.xml
. Se la richiesta non è una multipart/form-data
richiesta, il filtro di caricamento del file continuerà semplicemente come se non fosse successo nulla. Se utilizzi filtri che vengono aggiunti automaticamente perché utilizzano annotazioni (ad esempio PrettyFaces), potresti dover aggiungere un ordine esplicito tramite web.xml. Vedere Come definire l'ordine di esecuzione del filtro servlet utilizzando le annotazioni in WAR
Solo se stai utilizzando il filtro di caricamento file PrimeFaces: ce Filter
n'è un altro nella tua webapp che viene eseguito prima del filtro di caricamento file PrimeFaces e ha eseguito una RequestDispatcher#forward()
chiamata. Di solito, i filtri di riscrittura degli URL come PrettyFaces lo fanno. Questo attiva il FORWARD
dispatcher, ma i filtri ascoltano per impostazione predefinita REQUEST
solo sul dispatcher.
Per risolvere questo problema, è necessario inserire il filtro di caricamento dei file PrimeFaces prima del filtro di inoltro o riconfigurare il filtro di caricamento dei file PrimeFaces per ascoltare anche il FORWARD
dispatcher:
<filter-mapping>
<filter-name>primeFacesFileUploadFilter</filter-name>
<servlet-name>facesServlet</servlet-name>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
C'è un annidato <h:form>
. Ciò è illegale in HTML e il comportamento del browser non è specificato. Il più delle volte, il browser non invierà i dati previsti al momento dell'invio. Assicurati di non fare il nido <h:form>
. Questo è completamente indipendentemente dal modulo enctype
. Basta non annidare affatto le forme.
Se hai ancora problemi, beh, esegui il debug del traffico HTTP. Apri il set di strumenti per sviluppatori del browser web (premi F12 in Chrome / Firebug23 + / IE9 +) e controlla la sezione Rete / Rete. Se la parte HTTP sembra a posto, esegui il debug del codice JSF. Metti un punto di interruzione FileUploadRenderer#decode()
e avanza da lì.
Salvataggio del file caricato
Dopo averlo finalmente fatto funzionare, la tua prossima domanda sarà probabilmente "Come / dove salvo il file caricato?". Bene, continua qui: Come salvare il file caricato in JSF .
web.xml
secondo la Guida per gli utenti di PrimeFaces. L'hai letto comunque? Ciò tuttavia non spiegherebbe perchémode="simple"
funziona per te.