Как заставить JSF загружать файл с помощью Apache Commons FileUpload - PullRequest
5 голосов
/ 07 февраля 2012

Я знаю, как сделать загрузку файлов с помощью Primefaces или с помощью Tomahawk, однако я пытаюсь сделать загрузку файлов с помощью Apache Commons FileUpload, и до сих пор у меня есть некоторые препятствия. Несмотря на то, что моя форма использует multipart/form-data, когда я отправляю свою форму, тип контента становится application/x-www-form-urlencoded. Вот мой код

<h:body>
    <h:form enctype="multipart/form-data">
        Upload File
        <input type="file" name="file"/>
        <p:commandButton value="Submit" action="#{viewBean.submit}"/>
    </h:form>
</h:body>

Вот мой ViewBean

@ManagedBean
@ViewScoped
public class ViewBean implements Serializable {
    public void submit() {
        String url = "/FileUploadServlet";
        FacesContext context = FacesContext.getCurrentInstance();
        try {
            String contentType = context.getExternalContext().getRequestContentType();
            context.getExternalContext().dispatch(url);
        } catch (Exception e) {
            logger.log(Level.SEVERE, "Exception when calling Servlet", e);
        } finally {
            context.responseComplete();
        }
    }
}

Поэтому, когда я пытаюсь напечатать тип содержимого выше, он показывает application/x-www-form-urlencoded. Если я добавлю ajax="false" к своему p:commandButton, то метод submit() даже не вызывается, но если я уберу enctype="multipart/form-data" (все еще сохраняю ajax="false"), то вызывается submit(), но он не является составным , это application/x-www-form-urlencoded, поэтому apache commons fileupload выдает исключение, поскольку оно не является составным. Похоже, что я делаю, я не могу получить запрос на участие в нескольких частях. Пожалуйста, помогите

1 Ответ

12 голосов
/ 07 февраля 2012

Поэтому, когда я пытаюсь напечатать тип содержимого выше, он показывает application / x-www-form-urlencoded.

<p:commandButton> отправляет по умолчанию запрос ajax уровня 1 XMLHttpRequest. Это не поддерживает multipart/form-data. Его поддерживает только уровень 2 XMLHttpRequest, но он поддерживается только в новейших браузерах (также поддерживающих HTML5) и не реализован ни в JSF JS API, ни в PrimeFaces JS API.


Если я добавлю ajax = "false" к моему p: commandButton, то метод submit () даже не будет вызван

Таким образом, однако, будет отправлено multipart/form-data . То, что метод submit не вызывается, это просто потому, что JSF до версии 2.2 не поддерживает multipart/form-data запросов из коробки. JSF собирает отправленные данные по умолчанию, используя request.getParameter() и getParameterMap() в базовом HTTP-запросе сервлета. Однако это вернет null, если используется кодировка, отличная от application/x-www-form-urlencoded. Поскольку JSF определяет метод действия, который должен быть вызван, на основе отправленных данных, он не сможет найти и вызвать его, когда данные null.

Теоретически, если вы создаете Filter, который использует Apache Commons FileUpload или новый Servlet 3.0 request.getPart() / getParts() для извлечения данных из multipart/form-data запрашивает и упаковывает текущий HTTP-запрос сервлета с пользовательской реализацией, которая переопределяет вызовы getParameter(), в которые предоставляется сопоставление извлеченных данных, тогда JSF сможет выполнить необходимую работу на основе результатов вызовов getParameter() , Вы можете найти конкретный пример использования API Servlet 3.0 в этой статье и тот же пример, который немного изменен для использования Apache Commons FileUpload в этом ответе .

Предстоящий JSF 2.2 будет иметь новый компонент <h:inputFile>, который можно привязать к свойству Servlet 3.0 Part.

<h:form enctype="multipart/form-data">
    <h:inputFile value="#{bean.file}" />
    <h:commandButton value="submit" action="#{bean.submit}" />
</h:form>

с

private Part file;

Окончательный выпуск JSF 2.2 запланирован на поздний конец первого квартала, но в настоящее время доступен как выпуск моментального снимка.

...