Sposób konfiguracji i rozwiązywania problemów <p:fileUpload>
zależy od wersji PrimeFaces.
Wszystkie wersje PrimeFaces
Poniższe wymagania dotyczą wszystkich wersji PrimeFaces:
enctype
Atrybutem <h:form>
musi być ustawiony na multipart/form-data
. Gdy tego nie ma, ładowanie AJAX może po prostu działać, ale ogólne zachowanie przeglądarki jest nieokreślone i zależy od składu formularza oraz marki / wersji przeglądarki internetowej. Po prostu zawsze określaj to jako bezpieczną stronę.
Używając mode="advanced"
(tj. Wysyłania AJAX, jest to ustawienie domyślne), upewnij się, że masz a <h:head>
w (głównym) szablonie. Zapewni to prawidłowe dołączenie niezbędnych plików JavaScript. Nie jest to wymagane w przypadku mode="simple"
(wysyłania bez AJAX), ale mogłoby to zepsuć wygląd i funkcjonalność wszystkich innych komponentów PrimeFaces, więc i tak nie chcesz tego przegapić.
W przypadku korzystania z mode="simple"
(tj. Przesyłania bez AJAX), Ajax musi być wyłączony na każdym przycisku / łączu poleceń PrimeFaces przez ajax="false"
i należy używać <p:fileUpload value>
z <p:commandButton action>
zamiast <p:fileUpload fileUploadListener>
(dla PrimeFaces <= 7.x) lub <p:fileUpload listener>
(dla PrimeFaces> = 8.x)
Tak więc, jeśli chcesz (automatycznie) przesyłać pliki z obsługą Ajax (uwaga <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!
}
Lub jeśli chcesz przesłać plik bez 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!
}
Należy pamiętać, że atrybuty związane z AJAX, takie jak auto
, allowTypes
, update
, onstart
, oncomplete
, etc są ignorowane w mode="simple"
. W takim przypadku nie trzeba więc ich określać.
Zauważ również, że powinieneś czytać zawartość pliku bezpośrednio wewnątrz wyżej wymienionych metod, a nie w innej metodzie bean wywołanej późniejszym żądaniem HTTP. Dzieje się tak, ponieważ zawartość przesłanego pliku jest objęta zakresem żądania, a zatem jest niedostępna w późniejszym / innym żądaniu HTTP. Każda próba odczytania go w późniejszym żądaniu najprawdopodobniej zakończy się java.io.FileNotFoundException
w pliku tymczasowym.
PrimeFaces 8.x
Konfiguracja jest identyczna z informacjami o wersji 5.x poniżej, ale jeśli twój słuchacz nie jest wywoływany, sprawdź, czy attriubute jest wywoływany, listener
a nie (tak jak w przypadku wersji pre 8.x)fileUploadListener
PrimeFaces 5.x
Nie wymaga to żadnej dodatkowej konfiguracji, jeśli używasz JSF 2.2, a Twoja faces-config.xml
wersja jest również zgodna z JSF 2.2. W ogóle nie potrzebujesz filtra przesyłania plików PrimeFaces. Jeśli nie jest dla Ciebie jasne, jak poprawnie zainstalować i skonfigurować JSF w zależności od używanego serwera docelowego, przejdź do Jak poprawnie zainstalować i skonfigurować biblioteki JSF przez Maven? oraz sekcja „Instalowanie JSF” na naszej stronie wiki JSF .
Jeśli jednak nie używasz jeszcze JSF 2.2 i nie możesz go zaktualizować (powinno to być łatwe, gdy jest już w kontenerze kompatybilnym z Servletem 3.0), musisz ręcznie zarejestrować poniższy filtr przesyłania plików PrimeFaces w web.xml
(przeanalizuje on multi żądanie części i wypełnij mapę parametrów zwykłego żądania, aby FacesServlet
kontynuować normalną pracę):
<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>
<servlet-name>
Wartość facesServlet
musi odpowiadać dokładnie wartość w <servlet>
wpisu javax.faces.webapp.FacesServlet
w tym samym web.xml
. Więc jeśli jest to np. Faces Servlet
, Musisz go odpowiednio edytować, aby pasował.
PrimeFaces 4.x
Ta sama historia, co w przypadku PrimeFaces 5.x, dotyczy również wersji 4.x.
Istnieje tylko potencjalny problem z pobraniem zawartości przesłanego pliku przez UploadedFile#getContents()
. null
Zwróci to, gdy zamiast Apache Commons FileUpload zostanie użyte natywne API. Zamiast tego musisz użyć UploadedFile#getInputStream()
. Zobacz też Jak wstawić wgrany obraz z p: fileUpload jako BLOB w MySQL?
Innym potencjalnym problemem związanym z natywnym interfejsem API jest pojawienie się komponentu wysyłającego w postaci, w której jest uruchamiane inne „zwykłe” żądanie ajax, które nie przetwarza komponentu do przesyłania. Zobacz także Przesyłanie plików nie działa z AJAX w PrimeFaces 4.0 / JSF 2.2.x - javax.servlet.ServletException: Żądanie typu content-type nie jest multipart / form-data .
Oba problemy można również rozwiązać, przełączając się na Apache Commons FileUpload. Szczegółowe informacje można znaleźć w sekcji PrimeFaces 3.x.
PrimeFaces 3.x
Ta wersja nie obsługuje natywnego przesyłania plików JSF 2.2 / Servlet 3.0. Musisz ręcznie zainstalować Apache Commons FileUpload i jawnie zarejestrować filtr przesyłania plików w web.xml
.
Potrzebujesz następujących bibliotek:
Muszą one znajdować się w ścieżce klas środowiska wykonawczego aplikacji internetowej. Korzystając z Mavena, upewnij się, że mają one przynajmniej zakres czasu wykonywania (domyślny zakres kompilacji jest również dobry). Podczas ręcznego przenoszenia plików JAR upewnij się, że trafiają do /WEB-INF/lib
folderu.
Szczegóły rejestracji filtra przesyłania plików można znaleźć w sekcji PrimeFaces 5.x powyżej. Jeśli używasz PrimeFaces 4+ i chcesz jawnie użyć Apache Commons FileUpload zamiast natywnego przesyłania plików JSF 2.2 / Servlet 3.0, musisz obok wspomnianych bibliotek i przefiltrować również poniższy parametr kontekstu w web.xml
:
<context-param>
<param-name>primefaces.UPLOADER</param-name>
<param-value>commons</param-value><!-- Allowed values: auto, native and commons. -->
</context-param>
Rozwiązywanie problemów
Jeśli nadal nie działa, oto inne możliwe przyczyny niezwiązane z konfiguracją PrimeFaces:
Tylko jeśli używasz filtra Prześlij plik PrimeFaces: Jest inna Filter
w webapp, która biegnie przed filtrem Prześlij plik PrimeFaces i już zużyte ciało żądanie np powołania getParameter()
, getParameterMap()
, getReader()
, etcetera. Treść żądania można przeanalizować tylko raz. Gdy wywołasz jedną z tych metod, zanim filtr przesyłania plików wykona swoje zadanie, filtr przesyłania plików otrzyma pustą treść żądania.
Aby to naprawić, musisz umieścić <filter-mapping>
filtr przesyłania plików przed drugim filtrem web.xml
. Jeśli żądanie nie jest multipart/form-data
żądaniem, filtr przesyłania plików będzie kontynuowany tak, jakby nic się nie stało. Jeśli używasz filtrów, które są dodawane automagicznie, ponieważ używają adnotacji (np. PrettyFaces), może być konieczne dodanie jawnej kolejności za pośrednictwem web.xml. Zobacz Jak zdefiniować kolejność wykonywania filtrów serwletów za pomocą adnotacji w WAR
Tylko jeśli używasz filtru przesyłania plików PrimeFaces: Filter
w Twojej aplikacji internetowej jest inna, która działa przed filtrem przesyłania plików PrimeFaces i wykonała RequestDispatcher#forward()
połączenie. Zwykle robią to filtry przepisujące adresy URL, takie jak PrettyFaces . Spowoduje to wyzwolenie programu FORWARD
rozsyłającego, ale filtry nasłuchują domyślnie REQUEST
tylko w programie wysyłającym.
Aby to naprawić, musisz albo umieścić filtr przesyłania plików PrimeFaces przed filtrem przekierowania, albo ponownie skonfigurować filtr przesyłania plików PrimeFaces, aby również nasłuchiwał w FORWARD
dyspozytorze:
<filter-mapping>
<filter-name>primeFacesFileUploadFilter</filter-name>
<servlet-name>facesServlet</servlet-name>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
Jest zagnieżdżony <h:form>
. Jest to nielegalne w HTML, a zachowanie przeglądarki jest nieokreślone. Najczęściej przeglądarka nie wysyła oczekiwanych danych po przesłaniu. Upewnij się, że nie zagnieżdżasz się <h:form>
. Jest to całkowicie niezależne od formy enctype
. Po prostu w ogóle nie zagnieżdżaj form.
Jeśli nadal masz problemy, cóż, zdebuguj ruch HTTP. Otwórz zestaw narzędzi programistycznych przeglądarki internetowej (naciśnij klawisz F12 w przeglądarce Chrome / Firebug23 + / IE9 +) i sprawdź sekcję Sieć / Sieć. Jeśli część HTTP wygląda dobrze, zdebuguj kod JSF. Umieść punkt przerwania FileUploadRenderer#decode()
i przejdź dalej.
Zapisywanie przesłanego pliku
Gdy w końcu zaczniesz działać, Twoje następne pytanie będzie prawdopodobnie brzmiało: „Jak / gdzie zapisać przesłany plik?”. Cóż, kontynuuj tutaj: Jak zapisać przesłany plik w JSF .
web.xml
zgodnie z Przewodnikiem użytkownika PrimeFaces. Czytałeś to mimo wszystko? To jednak nie wyjaśnia, dlaczegomode="simple"
działa dla Ciebie.