提交后如何清空t:inputFileUpload组件的文件数据
解决JSF文件上传后刷新页面重复提交的问题
这个问题其实是浏览器表单重提交的经典场景,我来帮你分析下原因和解决办法:
问题根源
你在后台把file设为null的操作只影响服务器端的ViewScoped Bean,但浏览器端的表单(尤其是<input type="file">)的选中文件数据会被浏览器缓存下来。当你提交表单后如果页面没有做重定向,刷新时浏览器会自动重新发送之前的POST请求,导致文件被重复提交。
解决方案
1. 采用Post/Redirect/Get (PRG) 模式(推荐)
这是解决表单重复提交的标准方案:提交表单后,服务器端重定向到目标页面(可以是当前页面),这样浏览器的历史记录里只会留下GET请求,刷新时就不会再发送之前的POST数据了。
修改你的submit方法,让它返回重定向的页面路径:
public String submit() throws IOException { VOCargueSegmento cargue = new VOCargueSegmento(); try { cargue.setArchivoCargue(UtilitariosLOB.uploadedFileToCLOB(file.getInputStream())); cargue.setNombreArchivo(file.getContentType()); cargue.setIdAutenticacion(1L); Entry<Long, String> r = (Entry<Long, String>) gestionParametrosEJB.cargarSegmentos(cargue); resultadoCargue = r.getKey(); idProceso = r.getValue(); // 重定向到当前页面(假设你的页面名为segmentos.xhtml) return "segmentos?faces-redirect=true"; } catch (SQLException | IllegalStateException e) { e.printStackTrace(); // 出错时返回null,停留在当前页面 return null; } finally { file = null; } }
同时修改页面的h:commandButton,把actionListener改成action(因为现在方法返回导航字符串):
<h:commandButton value="#{general.importar}" class="btn btn-davivienda" action="#{segmentosMB.submit}"> </h:commandButton>
2. 前端重置表单(辅助优化)
配合PRG模式,你可以在表单提交完成后,通过JS重置表单,清除浏览器端的文件输入状态,让用户体验更好:
给表单添加ID,然后用AJAX的oncomplete事件执行重置:
<h:form id="uploadForm" enctype="multipart/form-data"> <t:inputFileUpload accept=".csv" value="#{segmentosMB.file}"> </t:inputFileUpload> <h:commandButton value="#{general.importar}" class="btn btn-davivienda" action="#{segmentosMB.submit}"> <f:ajax execute="@form" render="@form" oncomplete="document.getElementById('uploadForm').reset();" /> </h:commandButton> </h:form>
3. 确认ViewScoped配置正确性
虽然这不是当前问题的核心,但要确保你的ViewScoped Bean配置正确:
- 检查
faces-config.xml里的Bean定义是否正确使用了@ViewScoped(或者XML里的view作用域) - 确保Bean是可序列化的(如果需要的话),避免因为序列化问题导致Bean被重新创建
内容的提问来源于stack exchange,提问作者Steven Diaz
相关产品推荐
相关产品推荐

