Способ настройки и устранения неполадок <p:fileUpload>
зависит от версии PrimeFaces.
Все версии PrimeFaces
Приведенные ниже требования применяются ко всем версиям PrimeFaces:
enctype
Атрибутом <h:form>
должен быть установлен в multipart/form-data
. Когда этого нет, загрузка ajax может просто работать, но общее поведение браузера не определено и зависит от состава формы и марки / версии веб-браузера. Просто всегда указывайте это на всякий случай.
При использовании mode="advanced"
(например, при загрузке ajax, это значение по умолчанию) убедитесь, что у вас есть <h:head>
(основной) шаблон. Это обеспечит правильное включение необходимых файлов JavaScript. Это не требуется для mode="simple"
(загрузки без ajax), но это нарушит внешний вид и функциональность всех других компонентов PrimeFaces, так что вы все равно не захотите пропустить это.
При использовании mode="simple"
(т.е. не АЯКС загрузки), то Аякс должен быть отключен на любых PrimeFaces команды кнопки / ссылки, ajax="false"
и вы должны использовать <p:fileUpload value>
с <p:commandButton action>
вместо <p:fileUpload fileUploadListener>
(для PrimeFaces <= 7.x) или <p:fileUpload listener>
(для PrimeFaces> = 8.x)
Итак, если вы хотите (автоматическую) загрузку файла с поддержкой ajax (обратите внимание <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!
}
Или, если вы хотите загрузить файл без использования 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!
}
Обратите внимание , что Ajax-связанные атрибуты , такие как auto
, allowTypes
, update
, onstart
, oncomplete
, и т.д., игнорируются в mode="simple"
. Так что в таком случае указывать их не нужно.
Также обратите внимание, что вы должны читать содержимое файла сразу внутри вышеупомянутых методов, а не в другом методе bean-компонента, вызванном более поздним HTTP-запросом. Это связано с тем, что содержимое загруженного файла ограничено областью запроса и, следовательно, недоступно в более позднем / другом HTTP-запросе. Любая попытка прочитать его в более позднем запросе, скорее всего, закончится java.io.FileNotFoundException
во временном файле.
PrimeFaces 8.x
Конфигурация идентична информации о версии 5.x ниже, но если ваш слушатель не вызывается, проверьте, вызывается ли attriubute, listener
а не (как в версиях до 8.x)fileUploadListener
PrimeFaces 5.x
Это не требует дополнительной настройки, если вы используете JSF 2.2, и ваша faces-config.xml
также объявлена соответствующей версией JSF 2.2. Вам совсем не нужен фильтр загрузки файлов PrimeFaces. Если вам неясно, как правильно установить и настроить JSF в зависимости от используемого целевого сервера, перейдите в раздел Как правильно установить и настроить библиотеки JSF через Maven? и раздел «Установка JSF» на нашей вики-странице JSF .
Однако, если вы еще не используете JSF 2.2 и не можете его обновить (это должно быть несложно, если вы уже используете контейнер, совместимый с Servlet 3.0), тогда вам необходимо вручную зарегистрировать указанный ниже фильтр загрузки файлов PrimeFaces web.xml
(он будет анализировать мульти часть запроса и заполните карту параметров обычного запроса, чтобы FacesServlet
можно было продолжить работу в обычном режиме):
<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>
Значение facesServlet
должно точно соответствовать значению в <servlet>
Входе javax.faces.webapp.FacesServlet
в том же самом web.xml
. Так что, например Faces Servlet
, вам нужно отредактировать его, чтобы он соответствовал.
PrimeFaces 4.x
Та же история, что и PrimeFaces 5.x, применима и к 4.x.
Есть только потенциальная проблема с получением содержимого загруженного файла UploadedFile#getContents()
. Это вернется, null
если вместо Apache Commons FileUpload используется собственный API. UploadedFile#getInputStream()
Вместо этого вам нужно использовать . См. Также Как вставить загруженное изображение из p: fileUpload как BLOB в MySQL?
Другая потенциальная проблема с собственным API проявляется, когда компонент загрузки присутствует в форме, в которой запускается другой «обычный» запрос ajax, который не обрабатывает компонент загрузки. См. Также Загрузка файла не работает с AJAX в PrimeFaces 4.0 / JSF 2.2.x - javax.servlet.ServletException: тип содержимого запроса не является multipart / form-data .
Обе проблемы также можно решить, переключившись на Apache Commons FileUpload. См. Подробности в разделе PrimeFaces 3.x.
PrimeFaces 3.x
Эта версия не поддерживает загрузку собственных файлов JSF 2.2 / Servlet 3.0. Вам необходимо вручную установить Apache Commons FileUpload и явно зарегистрировать фильтр загрузки файлов в web.xml
.
Вам потребуются следующие библиотеки:
Они должны присутствовать в пути к классам времени выполнения веб-приложения. При использовании Maven убедитесь, что они, по крайней мере, относятся к области выполнения (область компиляции по умолчанию также хороша). При переносе JAR-файлов вручную убедитесь, что они попали в /WEB-INF/lib
папку.
Подробную информацию о регистрации фильтра загрузки файлов можно найти в разделе PrimeFaces 5.x выше. Если вы используете PrimeFaces 4+ и хотите явно использовать Apache Commons FileUpload вместо загрузки собственного файла JSF 2.2 / Servlet 3.0, тогда вам нужно рядом с упомянутыми библиотеками и фильтровать также параметр контекста ниже в web.xml
:
<context-param>
<param-name>primefaces.UPLOADER</param-name>
<param-value>commons</param-value><!-- Allowed values: auto, native and commons. -->
</context-param>
Исправление проблем
Если это все еще не работает, вот другие возможные причины, не связанные с конфигурацией PrimeFaces:
Только если вы используете фильтр загрузки PrimeFaces файла: Там другая Filter
в вашем веб - приложение , которое работает до того фильтра Загружайте PrimeFaces файл и уже поглотил тело запроса, например , путем вызова getParameter()
, getParameterMap()
, getReader()
, и так далее. Тело запроса можно проанализировать только один раз. Когда вы вызываете один из этих методов до того, как фильтр загрузки файлов выполнит свою работу, фильтр загрузки файлов получит пустое тело запроса.
Чтобы исправить это, вам нужно будет поместить <filter-mapping>
фильтр загрузки файлов перед другим фильтром web.xml
. Если запрос не является multipart/form-data
запросом, тогда фильтр загрузки файла продолжит работу, как будто ничего не произошло. Если вы используете фильтры, которые добавляются автоматически, поскольку они используют аннотации (например, PrettyFaces), вам может потребоваться добавить явное упорядочивание через web.xml. См. Как определить порядок выполнения фильтра сервлетов с помощью аннотаций в WAR
Только если вы используете фильтр загрузки файлов PrimeFaces: Filter
в вашем веб-приложении есть еще один, который запускается перед фильтром загрузки файлов PrimeFaces и выполнил RequestDispatcher#forward()
вызов. Обычно это делают фильтры перезаписи URL, такие как PrettyFaces . Это запускает FORWARD
диспетчер, но фильтры по умолчанию прослушивают только REQUEST
диспетчер.
Чтобы исправить это, вам нужно либо поставить фильтр загрузки файлов PrimeFaces перед фильтром пересылки, либо перенастроить фильтр загрузки файлов PrimeFaces, чтобы также прослушивать FORWARD
диспетчер:
<filter-mapping>
<filter-name>primeFacesFileUploadFilter</filter-name>
<servlet-name>facesServlet</servlet-name>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
Есть вложенный <h:form>
. Это недопустимо в HTML, и поведение браузера не определено. Чаще всего браузер не отправляет ожидаемые данные при отправке. Убедитесь, что вы не гнездитесь <h:form>
. Это совершенно независимо от формы enctype
. Только формы гнезда вообще не надо.
Если у вас все еще возникают проблемы, отладьте HTTP-трафик. Откройте набор инструментов разработчика веб-браузера (нажмите F12 в Chrome / Firebug23 + / IE9 +) и проверьте раздел Net / Network. Если часть HTTP выглядит нормально, отладьте код JSF. Установите точку останова FileUploadRenderer#decode()
и двигайтесь дальше .
Сохранение загруженного файла
После того, как вы наконец заставите его работать, ваш следующий вопрос, вероятно, будет типа «Как / где мне сохранить загруженный файл?». Что ж, продолжаем здесь: Как сохранить загруженный файл в JSF .
web.xml
соответствии с Руководством пользователя PrimeFaces. Вы все равно это читали? Однако это не объясняет, почемуmode="simple"
работает для вас.