SpringMVC之表单提交===③===多文件上传表单 http://h-king.iteye.com/blog/2269217

来源:互联网 发布:招牌设计软件 编辑:程序博客网 时间:2024/05/16 03:45

上文简单介绍了springmvc单文件上传表单 ,本文继续介绍多文件上传表单。包含单文件上传的表单已经能够满足大部分功能需求,但任然不够完善。实际业务中可能会包含多个文件同时上传,例如:商家在电商平台申请店铺需要上传身份证扫描文件,这时会有两份上传文件(正/反面)。此时,单文件表单就不能满足需求了;当然你也可以把多个文件拆分为多个表单,关于业务实际问题不在本文讨论范围之内。

 

在很多时候并不是说问题本身有多难,难的是把问题找出来。只要能把疑问命题找到,距离解决问题也就相差0.1毫米;所以,springmvc 对多文件上传这个问题域有多种解决方案,下面介绍 springmvc 是如何支持多文件上传的!

 

方案一:使用数组接受表单文件 org.springframework.web.multipart.MultipartFile[]

  • 创建多个文件域,当前测试用例表单中文件域数据不固定
Jsp代码  收藏代码
  1. <!-- 定义表单结构 -->  
  2. <div id="normal_form" class="form"><!-- 多文件上传 -->  
  3.     <h2 class="intro">C. 多文件上传表单</h2>  
  4.     <form class="hidden" action="<%=basePath %>form/uploadMore.do" method="post" enctype="multipart/form-data">  
  5.         <p>  
  6.             <label for="upFile1">选择要上传的文件:</label>  
  7.             <input type="file" name="multipartFiles" />  
  8.         </p>  
  9.           
  10.         <p>  
  11.             <input type="button" id="addFileItem" value="Add File Item" />  
  12.             &nbsp;  
  13.             &nbsp;  
  14.             &nbsp;  
  15.             <input type="submit" value="Submit" />  
  16.         </p>  
  17.     </form>  
  18. </div><!-- /多文件上传 -->  

 

  •  添加事件
Js代码  收藏代码
  1. window.console && console.log("form.js");  
  2.   
  3. $(function() {  
  4.     var thisPageFn = new FormNormalFn();  
  5.     thisPageFn.initEvents();  
  6.     thisPageFn.initData();  
  7.     window.console && console.log("Page load event is complete");  
  8. });  
  9.   
  10. /** 
  11.  * @description form.jsp 页面交互 
  12.  * @author Huang.Yong 
  13.  * @version 0.1 
  14.  * @date 2016年1月5日 - 下午6:16:04 
  15.  */  
  16. function FormNormalFn() {  
  17.     var $thisObj = this;  
  18.     var baseCtt = $("body");  
  19.   
  20.     /** 
  21.      * 初始化事件 
  22.      */  
  23.     this.initEvents = function() {  
  24.         // 展示隐藏  
  25.         $(".intro").click(function(){  
  26.             $(this).parent().find("form").toggleClass("hidden");  
  27.         });  
  28.           
  29.         // 添加上传文件项  
  30.         $("#addFileItem").click(function(){  
  31.             var $this = $(this);  
  32.             var btnCtn = $this.parent();  
  33.               
  34.             var p =$("<p/>").insertBefore(btnCtn);  
  35.             p.append($("<input/>",{  
  36.                 type : "file",  
  37.                 name : "multipartFiles"  
  38.             })).append($("<input/>",{  
  39.                 type : "button",  
  40.                 value : " X "  
  41.             }).click(function(){  
  42.                 var $delBtn = $(this);  
  43.                 $delBtn.parent().remove();  
  44.             }));  
  45.         });  
  46.     }  
  47.   
  48.     /** 
  49.      * 初始化数据 
  50.      */  
  51.     this.initData = function() {  
  52.     }  
  53.   
  54.     /** 
  55.      * 日志记录 
  56.      */  
  57.     function log(msg) {  
  58.         window.console && console.log(msg);  
  59.     }  
  60.   
  61.     return this;  
  62. }  

 

  • 定义控制器接口
Java代码  收藏代码
  1. /** 
  2.  * @Title: uploadMore 
  3.  * @Description: 多文件上传 
  4.  * @param multipartFiles 
  5.  * @return ModelMap 
  6.  */  
  7. @RequestMapping("/uploadMore")  
  8. @ResponseBody  
  9. public ModelMap uploadMore(@RequestParam("multipartFiles") MultipartFile[] multipartFiles) {  
  10.     boolean flag = false;  
  11.     String message = null;  
  12.     List<ModelMap> data = Lists.newArrayList();  
  13.   
  14.     try {  
  15.         for (MultipartFile multipartFile : multipartFiles) {  
  16.             System.out.println(multipartFile.getName() + "-----" + multipartFile.getOriginalFilename());  
  17.             ModelMap uploadOne = uploadOne(multipartFile);  
  18.             data.add(uploadOne);  
  19.         }  
  20.   
  21.         flag = true;  
  22.     } catch (Exception e) {  
  23.         flag = false;  
  24.         message = "";  
  25.         LOGGER.warn(message + " : " + e.getMessage(), e);  
  26.     }  
  27.   
  28.     return WebUtil.getModelMap(flag, data, message);  
  29. }  

 tips:此种方式上传多个文件有两个地方需要特别注意,

  ①表单类型enctype="multipart/form-data"以及表单名称<input type="file" name="multipartFiles" />;

  ②控制器参数名称public ModelMap uploadMore(@RequestParam("multipartFiles") MultipartFile[] multipartFiles)

 

结果验证:

当前选择三个需要上传的文件

 

断点查看控制器:



 

 由此可见,文件已上传成功!不过此方法有些缺陷:

  1. 表单文件域名称必须与接口中数组参数名一致
  2. 只能根据参数 multipartFiles 下标值区分文件,一旦UI中文件域位置调整就会产生严重后果(如:身份证文件营业执照文件对调等)

方案二:表单实体(FormEntities)+ 请求对象(HttpServletRequest)

  • 定义复杂表单

 

Html代码  收藏代码
  1. <div id="normal_form" class="form"><!-- 复杂文件上传表单 -->  
  2.     <h2 class="intro">D. 复杂文件上传表单</h2>  
  3.     <form class="hidden" action="<%=basePath %>form/complexForm.do" method="post" enctype="multipart/form-data">  
  4.         <p>  
  5.             <label for="form4_item1" class="title">文本框:</label>  
  6.             <input type="text" id="form4_item1" class="item" name="formText" />  
  7.         </p>  
  8.         <p>  
  9.             <label for="form4_item2" class="title">密码框:</label>  
  10.             <input type="password" id="form4_item2" class="item" name="formPwd" />  
  11.         </p>  
  12.         <p>  
  13.             <label>单选:</label>  
  14.             <input type="radio" id="form1_item3" class="item" name="formRadios" value="rdo1" />  
  15.             <label for="form1_item3">单选一</label>  
  16.             &nbsp;  
  17.             &nbsp;  
  18.             <input type="radio" id="form1_item32" class="item" name="formRadios" value="rdo2" />  
  19.             <label for="form1_item32">单选二</label>  
  20.             &nbsp;  
  21.             &nbsp;  
  22.             <input type="radio" id="form1_item33" class="item" name="formRadios" value="rdo3" />  
  23.             <label for="form1_item33">单选三</label>  
  24.         </p>  
  25.         <p>  
  26.             <label>复选:</label>  
  27.             <input type="checkbox" id="form4_item4" class="item" name="formCheckboxes" value="复选框1" />  
  28.             <label for="form4_item4" class="title">复选一</label>  
  29.             &nbsp;  
  30.             &nbsp;  
  31.             <input type="checkbox" id="form4_item5" class="item" name="formCheckboxes" value="复选框2" />  
  32.             <label for="form4_item5" class="title">复选二</label>  
  33.             &nbsp;  
  34.             &nbsp;  
  35.             <input type="checkbox" id="form4_item6" class="item" name="formCheckboxes" value="复选框3" />  
  36.             <label for="form4_item6" class="title">复选三</label>  
  37.         </p>  
  38.         <p>  
  39.             <label for="form4_sl">下拉:</label>  
  40.             <select name="formSl" id="form1_sl">  
  41.                 <option value="value1">下拉1</option>  
  42.                 <option value="value2">下拉2</option>  
  43.                 <option value="value3">下拉3</option>  
  44.                 <option value="value4">下拉4</option>  
  45.                 <option value="value5">下拉5</option>  
  46.             </select>  
  47.         </p>  
  48.         <p>  
  49.             <label for="form4_txta" style="left:left;">多行文本:</label>  
  50.             <textarea name="formTxt" id="form4_txta" cols="30" rows="10" style="resize:none;left:left;"></textarea>  
  51.         </p>  
  52.         <p>  
  53.             <input type="button" class="addFileItem2" value="Add File Item" />  
  54.             &nbsp;  
  55.             &nbsp;  
  56.             &nbsp;  
  57.             <input type="submit" value="Submit" />  
  58.         </p>  
  59.     </form>  
  60. </div><!-- /复杂文件上传表单 -->  

 

  •  表单事件,点击【Add File Item】添加一个新的文件域,且文件域name值不能相同

 

Js代码  收藏代码
  1. // 添加上传文件项  
  2. $(".addFileItem2").click(function(){  
  3.     var $this = $(this);  
  4.     var btnCtn = $this.parent();  
  5.       
  6.     var p =$("<p/>").insertBefore(btnCtn);  
  7.     p.append($("<input/>",{  
  8.         type : "file",  
  9.         name : "multipartFiles_" + (new Date().getTime())  // 每次不同  
  10.     })).append($("<input/>",{  
  11.         type : "button",  
  12.         value : " X "  
  13.     }).click(function(){  
  14.         var $delBtn = $(this);  
  15.         $delBtn.parent().remove();  
  16.     }));  
  17. });  

 

  • 开发控制器接口

 

Java代码  收藏代码
  1. /** 
  2.  * @Title: complexForm 
  3.  * @Description: 映射复杂表单 
  4.  * @param form 表单实体映射 
  5.  * @param request 请求对象 
  6.  */  
  7. @RequestMapping("/complexForm")  
  8. @ResponseBody  
  9. public ModelMap complexForm(SimpleForm form, HttpServletRequest request) {  
  10.     boolean flag = false;  
  11.     String message = null;  
  12.     Map<String, Object> data = Maps.newLinkedHashMap();  
  13.   
  14.     try {  
  15.         // 表单数据  
  16.         data.put("formData", form);  
  17.   
  18.         // 获取附件  
  19.         // 如果是文件上传: request.getClass() == MultipartHttpServletRequest.class  
  20.         if (request instanceof MultipartHttpServletRequest) {  
  21.             MultipartHttpServletRequest multipartReq = (MultipartHttpServletRequest) request;  
  22.             Map<String, MultipartFile> fileMap = multipartReq.getFileMap();  
  23.   
  24.             // 上传到指定位置  
  25.             if (MapUtils.isNotEmpty(fileMap)) {  
  26.                 int count = 1;  
  27.                 for (Entry<String, MultipartFile> me : fileMap.entrySet()) {  
  28.                       
  29.                     // 表单项名称  
  30.                     String formItemName = me.getKey();  
  31.                     // 与表单项名称关联的唯一附件  
  32.                     MultipartFile multipartFile = me.getValue();  
  33.   
  34.                     // do something  
  35.                     ModelMap uploadOne = this.uploadOne(multipartFile);  
  36.                     data.put(formItemName + count, uploadOne);  
  37.                     count++;  
  38.                 }  
  39.             }  
  40.         }  
  41.   
  42.         flag = true;  
  43.     } catch (Exception e) {  
  44.         flag = false;  
  45.         message = "";  
  46.         LOGGER.warn(message + " : " + e.getMessage(), e);  
  47.     }  
  48.   
  49.     return WebUtil.getModelMap(flag, data, message);  
  50. }  

 

Tips:使用此种方式上传多个文件附件时,文件域name值不能一致(name作为 Map 的 Key 值);如果可以确定一致性,则推荐使用方案一

 

结果验证:

选择需要上传的文件:

断点控制器观察文件列表:



通过结果观察表单其他数据:



 

 

至此,关于 springmvc 表单映射已记录完成;其中更多细节部分可以下载附件:ssmFU.zip(maven)查阅研究,欢迎留言探讨学习。

  • ssmFU.zip (135.1 KB)
  • 下载次数: 7
  • 查看图片附件
0 0
原创粉丝点击