【发布时间】:2019-02-28 09:29:55
【问题描述】:
考虑一个带有 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>
还有后台bean:
@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 方法可以在提交时上传多个文件,但我错过了?
【问题讨论】:
-
你在哪里读到 "JSF
标签、Primefaces ?根据我的理解,这不是真的标签和 Omnifaces 标签都要求用户上传文件作为提交前的显式操作,并为此提供一个方便的“上传”按钮。" -
p:fileUpload,h:inputFile和o:inputFile都渲染一个input type="file"btw,所以它完全是 HTML5,而且它们都没有上传按钮......所以我很好奇如何你得出了你的结论。他们还支持ajax上传顺便说一句,所以选择时会自动上传。 -
我现在无法创建测试,因为我只有手机。您是否有需要显式上传按钮的minimal reproducible example
-
我不明白你的核心问题。您是否想问如何使输入字段成为必需?如果是这样,为什么不像往常一样设置
required="true"属性?或者,您是否想问如何在业务操作中区分上传的文件和未上传的文件?如果是这样,你为什么不做一个if(file!=null)检查?您似乎很适合做任何一个,这就是为什么这个问题如此令人困惑的原因。 -
感谢您抽出宝贵时间回复,对于我的原始帖子中缺乏清晰性和错误,我深表歉意。我对 Omnifaces 组件的理解是错误的。我用一个丑陋但 MCV 的例子更新了这篇文章。核心问题实际上是围绕 PF 组件所需的附加“上传”操作的可用性。我没有想过将 PF 文件上传小部件标记为必需,这会起作用,除了在我当前的用例中,提交支持请求票证时,用户通常不会提交任何文件。
标签: jsf file-upload primefaces usability omnifaces