上传单个文件
1.定义具有文件上传功能的页面 index.jsp,其表单的设置需要注意,method 属性为 POST,
enctype 属性为 multipart/form-data。另外,需要注意 file 表单元素的参数名称,Controller 中需要使用
2.定义处理器
1 public class MyController { 2 3 @RequestMapping(value = "/upload.do") 4 public String fileUpload(HttpSession session,MultipartFile img) throws Exception { 5 // 用于接收文件的形参类型不是File,而是MultipartFile,MultipartFile 是一个接口,专门用于处理文件上传 6 //如没有点击上传文件,直接提交,mulFile也不会为null,而是一个内容为empty的文件,所以不能用 null 来判断 7 if(img.getSize() > 0) { 8 //目录必须提前创建,因为 transferTo 方法不会创建目标目录 9 String path = session.getServletContext().getRealPath("images"); 10 //得到原始文件名 11 String fileName = img.getOriginalFilename(); 12 //限制文件上传类型 13 if(fileName.endsWith("jpg") || fileName.endsWith("png")) { 14 File file = new File(path ,fileName ); 15 //进行文件上传 16 img.transferTo(file); 17 } 18 else{ 19 return "/error.jsp"; 20 } 21 22 } 23 return "/success.jsp"; 24 } 25 26 }
1.用于接收表单元素所提交参数的处理器方法的形参类型不是 File,而是 MultipartFile。
MultipartFile 为一个接口,专门用于处理文件上传问题。该接口中具有很多有用的方法,
例 如 获 取 参 数 名 称 getName() ; 获 取 文 件 的 原 始 名 称 getOriginalFilename();
获取文件大小 getSize();判断文件是否为空 isEmpty();文件上传 transferTo()等。
2.若用户未选择上传的文件就直接提交了表单,此时处理器方法的 MultipateFile 形参所接 收到的实参值并非为 null,
而是一个内容为 empty 的文件。所以,对于未选择上传文件的情 况的处理,其判断条件为 file.isEmpty(),而非 file == null。
3.SpringMVC 的文件上传功能并未有直接的用于限定文件上传类型的方法或属性,需要对 获取到的文件名后辍加以判断。
此时使用 String 的 endWith()方法较为简捷。
4.对于上传单个文件,直接使用 MultipartFile 的 transferTo()方法,就可以完成上传功能。
但是,需要注意的是,该方法要求服务端用于存放客户上传文件的目录必须存在,否则报错。
即其不会自己创建该目标目录。如本例中,必须手工创建 images 目录。
3.注册文件上传处理器
1 <!-- 注册 multipartResolver 解析器,这个id 只能这样写 ,DisPatcherServlet(中央调度器) 会去通过这个id调用 这个bean--> 2 <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> 3 <!-- 可以在这里进行一些属性的 设置 --> 4 <property name="defaultEncoding" value="UTF-8"></property> 5 <property name="maxUploadSize" value="1000000"></property> 6 </bean> 7 8 <!-- 文件上传 需要使用 mvc 注解驱动,因为 MultipartFile 是一个接口,这个接口实现类的 创建 依赖于 mvc 注解驱动--> 9 <mvc:annotation-driven /> 10 11 <!--当上传文件超出指定大小时,会抛出异常, 异常处理器 --> 12 <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> 13 <property name="defaultErrorView" value="/error.jsp"></property> 14 </bean>
分析源码可以得到以下过程:
如果容器中定义了名称为 multipartResolver 的 Bean,且请求也为 multipart 类型(即enctype 属性值为 multipart/form-data),
则返回 MultipartHttpServletRequest 请求类型,完成 文件上传功能。否则,返回普通的 HttpServletRequest 请求类型。
多个文件
1.用于接收表单元素所提交参数的处理器方法的形参类型为 MultipartFile 数组,且必须使用注解@RequestParam 修饰。
为什么上传单个文件时 MultipartFile 参数不用使用@RequestParam 修饰,
而上传多个文 件时 MultipartFile[]就需要@RequestParam 修饰呢?
因为在上传多个文件时,每个表单中的文件对象框架均会将其转换为 MultipartFile 类型,
这是与上传单个文件是相同的,不需要@RequestParam 修饰。但上传多个文件时,
处理器方 法需要的不是 MultipartFile 类型参数,而是 MultipartFile[]数组类型。
默认情况下框架只会将 一个一个的表单元素转换为一个一个的对象,但并不会将这多个对象创建为一个数组对象。
此时,需要使用@RequestParam 来修饰这个数组参数,向框架表明,
表单传来的参数与 处理器方法接收的参数名称与类型相同,需要框架调用相应的转换器将请求参数转换为方法 参数类型。
所以,对于上传多个文件,处理器方法的 MultipartFile[]数组参数必须使用注解@RequestParam 修饰。
2.选择上传文件
即使没有选择任何要上传的文件,MultipartFile 数组也不为 null。不仅不为 null,其 length 值也大于 0。
因为系统会为每个 file 表单元素创建一个 File 对象,只不过没有选择上传文件 的这个 File 将不会被赋予真正的文件,
只是一个为 empty 的 File。所以对于没有选择任何要上传的文件的情况的处理,
只能逐个文件表单元素进行判断,判断文件是否为 empty。
1 public class MyController { 2 3 @RequestMapping(value = "/upload.do") 4 //上传多个文件,使用的 形参类型为MultipartFile数组,且必须使用 注解 @RequestParam 5 //上传多个文件时,处理器方法需要的不是 Multipart ,而是MultipartFile[] ,默认情况下框架只会将一个一个的表单元素转换成一个一个的对象,并不会将这多个对象创建为一个数组对象 6 //使用 @RequestParam 来修饰,想框架表明,我就是要用 数组类型的,给我创建 7 public String fileUpload(HttpSession session,@RequestParam MultipartFile[] imgs) throws Exception { 8 // 用于接收文件的形参类型不是File,而是MultipartFile,MultipartFile 是一个接口,专门用于处理文件上传 9 //如没有点击上传文件,直接提交,mulFile也不会为null,而是一个内容为empty的文件,所以不能用 null 来判断 10 for(MultipartFile img:imgs) { 11 if(img.getSize() > 0) { 12 //目录必须提前创建,因为 transferTo 方法不会创建目标目录 13 String path = session.getServletContext().getRealPath("images"); 14 //得到原始文件名 15 String fileName = img.getOriginalFilename(); 16 //限制文件上传类型 17 if(fileName.endsWith("jpg") || fileName.endsWith("png")) { 18 File file = new File(path ,fileName ); 19 //进行文件上传 20 img.transferTo(file); 21 } 22 else{ 23 return "/error.jsp"; 24 } 25 26 } 27 } 28 return "/success.jsp"; 29 } 30 31 }