Загрузка файла и отправка формы - PullRequest
0 голосов
/ 24 сентября 2018

Рассмотрим форму с компонентом fileUpload.Пользователь выбирает некоторые файлы с помощью компонента fileUpload, а затем отправляет форму, разумно полагая, что выбранные файлы неявно передаются вместе с формой, но это не так.Компонент Primefaces fileUpload требует от пользователя загрузить файлы в качестве явного действия перед отправкой и предоставить для этого удобную кнопку «Загрузить».Однако, если пользователь не делает этого, форма отправляется без файлов и без указания того, что они были исключены из отправки.В некоторых случаях файлы могут быть позже не прикреплены к объекту, созданному при отправке формы.Напротив, компоненты JSF и Omnifaces inputFile и HTML5 <input type="file">, на которых они основаны, загружают файлы при отправке, что мне кажется более удобным.

Вот пример кода.Сначала презентация:

    <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
        xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:p="http://primefaces.org/ui">
    <h:head></h:head>
    <h:body>
        <f:view>
            <h:form id="form" enctype="multipart/form-data" method="POST">
                <p:panelGrid id="grid" columns="2" cellpadding="15">
                    <p:outputLabel>HTML5 input type="file"</p:outputLabel>
                    <input type="file" id="fileupload1" name="fileupload1" multiple="multiple" />
                    <p:outputLabel>Primefaces fileUpload</p:outputLabel>
                    <p:fileUpload id="fileupload2" fileUploadListener="#{myBean.handleFileUpload}" multiple="true" />
                    <p:outputLabel>JSF Input File</p:outputLabel>
                    <h:inputFile id="fileupload3" value="#{myBean.uploadedFile}" />
                </p:panelGrid>
                <p:commandButton id="submit" value="Submit" actionListener="#{myBean.submit}" process="@form" ajax="false" />
            </h:form>
        </f:view>
    </h:body>
    </html>

И вспомогательный компонент:

@ManagedBean
@SessionScoped
public class MyBean {

    private Map<String, Path> uploadedFiles = new HashMap<String, Path>();
    Part uploadedFile;

    public void handleFileUpload(FileUploadEvent event) {
        System.out.println("Uploaded file: " + event.getFile().getFileName());
    }

    public void submit(ActionEvent actionEvent) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
        for (Part part : request.getParts()) {
            if (part != null && part.getSize() > 0 && part.getSubmittedFileName() != null) {
                String fileName = part.getSubmittedFileName();
                String contentType = part.getContentType();
                System.out.println("File in request: " + fileName + "; contentType " + contentType + "; size: " + part.getSize());
            }
        }
        System.out.println("Primefaces uploaded Files (" + (uploadedFiles == null ? "0" : uploadedFiles.size()) + "):");
        if (uploadedFiles != null) {
            for (String name : uploadedFiles.keySet()) {
                System.out.println("     Name: " + name + "; Path " + uploadedFiles.get(name));
            }
        }
        System.out.println("JSF uploaded file: " + (uploadedFile == null ? "null" : uploadedFile.getSubmittedFileName() + ", size " + uploadedFile.getSize()));
    }

    public Part getUploadedFile() {
        System.out.println("get uploaded File Part: " + (uploadedFile == null ? "none" : uploadedFile.getSubmittedFileName()));
        return uploadedFile;
    }

    public void setUploadedFile(Part uploadedFile) {
        System.out.println("set uploaded File Part: " + (uploadedFile == null ? "none" : uploadedFile.getSubmittedFileName()));
        this.uploadedFile = uploadedFile;
    }
}

Если вы отправляете эту форму после выбора файлов во всех трех компонентах загрузки файлов, единственный Primefaces один, которыйне загружает файлы при отправке.Конечно, вы можете установить для «auto» значение true, чтобы оно загружало файлы при выборе, но тогда нет способа отказаться, если пользователь решит не загружать файл.Вы можете установить его как обязательный, но в общем случае пользователь может не захотеть загружать какой-либо файл.Таким образом, кажется, что компонент Primefaces является шагом назад в этом отношении, хотя он очень прост в использовании и более полнофункциональный.

Существует ли способ Primefaces для загрузки нескольких файлов в момент отправки, который мне не хватает?

1 Ответ

0 голосов
/ 27 сентября 2018

Спасибо @Kukeltje за помощь в поиске ответа.

«Простые» виджеты загрузки файлов, такие как HTML5 <input type="file">, JSF's <h:inputFile> и Omnifaces <o:inputFile>, позволяют пользователю выбрать один или несколько файлов, которые будут загружены во время отправки.

Некоторые более сложные виджеты fileUpload, такие как Primefaces один (с mode="advanced", режим по умолчанию и multiple="true"), позволяют пользователю загружать несколько файлов за один клик ДО времени отправки, но если пользователь не делает этого, то выбранные файлыне загружены во время отправки.Виджет PF может использоваться с mode="simple", если разработчик хочет избежать проблемы юзабилити, когда пользователь предполагает, что выбранные файлы загружены во время отправки, а это не так.Преимущества использования виджета PF таким способом заключаются в эстетичности и возможности выбора нескольких файлов.

В качестве сноски, не связанной с исходным вопросом, в частности, существует проблема с виджетом PF и, возможно, с другимипохожие в похожих рамках.В простом режиме, если пользователь выбирает несколько файлов, виджет отображает только первый выбранный файл.

Я вижу еще одну проблему, когда после того, как пользователь выбрал несколько файлов в ЛЮБОМ из этих виджетов, которые разрешают использование нескольких, эти файлы не могут быть отменены.После экспериментов с JS для отображения списка выбранных файлов я обнаружил, что в JS не могу изменить список из-за безопасности браузера, см. Ответ BalusC здесь .В итоге я получил простой JS, который при отправке проверяет, есть ли на виджете загрузки PF какие-либо выбранные файлы, и, если это так, предотвращает отправку и просит пользователя загрузить файлы перед отправкой.Я думаю, что это наиболее полезное решение.

<p:commandButton value="Submit" actionListener="#{bean.submit}" onclick="return checkAttachments();" ajax="false" />

<script>
function checkAttachments() {
    var attachmentRows = $(".ui-fileupload-row");
    console.log("rows " + attachmentRows.length);
    if (attachmentRows.length == 0 ) {
        return true;
    }
    PF('uploadAttachmentsWarningDialog').show();
    return false;
}
</script>
...