1.spring提供了CommonsMultipartResolver解析器,用于实现文件上传功能
2.pom.xml文件中添加依赖包 commons-fileupload-1.3.1、commons-io-2.2、commons-logging-1.0.4
3.jsp页面(注意:以下是基于spring-mvc已经配置好的情况下使用的)
在form表单中,需要设置method="post",还要设置enctype="multipart/form-data"
<!-- 单文件上传 --> <form action="${basePath }/upload/file1" method="post" enctype="multipart/form-data"> <input type="file" name="file1" > <input type="submit" value="上传"> </form>
在后台Controller中实现上传
1 /** 2 * 实现图片上传,并且跳转到一个视图页面进行显示 3 * 4 * 1.MultipartFile:springmvc会自动的通过文件上传解析器,将表单的文件等信息转成MultipartFile接口类型子类对象 5 * 2.方法中的参数名file1需要与表单中的文件上传组件的name一致 6 * @return 7 */ 8 9 @RequestMapping("/file1") 10 public String fileUpload1(MultipartFile file1,HttpServletRequest request,HttpServletResponse response){ 11 //获取上传的文件原名 12 String filename=file1.getOriginalFilename(); 13 System.out.println(filename); 14 //获取服务器真实物理路径 15 String realPath = request.getServletContext().getRealPath("file"); 16 System.out.println("当前真实物理路径为:"+realPath); 17 File targetFile = new File(realPath, filename); 18 response.setContentType("text/html;charset=utf-8"); 19 if(!targetFile.exists()){ 20 targetFile.mkdirs();//递归创建当前文件的父文件夹 21 } 22 try { 23 file1.transferTo(targetFile); 24 String url=request.getContextPath()+File.separator+"file"+File.separator+filename; 25 request.setAttribute("url", url); 26 } catch (IllegalStateException | IOException e) { 27 e.printStackTrace(); 28 } 29 return "fileView"; 30 }
jsp页面显示上传的图片
<body> fileView.jsp ${url } <img alt="tupian" src="${url }"> </body>
配置文件上传解析器multipartResolver(由于设置了Restful,需要指定静态资源匹配)
<!-- 配置上传的文件的静态资源访问映射 --> <mvc:resources location="/file/" mapping="/file/**"></mvc:resources> <!-- 配置文件上传解析器multipartResolver 必须按照该固定bean的id值来设置,否则不生效 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 设置总上传文件大小 单位是字节 --> <!-- <property name="maxUploadSize" value="104857"></property> 设置延迟解析为true 才能让自定义异常生效 <property name="resolveLazily" value="true"></property> --> </bean>
中文文件名上传引发的一些乱码问题!!!
A.中文名称文件使用post方式上传
使用spring提供的编码过滤器可以解决中文乱码问题(前提:项目统一编码)
<!-- 通过spring提供的过滤器解决乱码问题 --> <filter> <filter-name>encodingFilter</filter-name> <filter-class> org.springframework.web.filter.CharacterEncodingFilter </filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
B.在html/jsp页面中,引用了带汉字的图片,如:<img src="/目录/子目录/图片名字.jpg" />,如果没有在tomcat配置URIEncoding,则无法显示。
jsp页面加载时,加载中文名的静态资源,出现乱码,自然就获取不到请求资源,无法加载了,jsp页面是没有乱码的。但是后台配置了编码过滤器的,为什么还会乱码呢?
jsp页面加载时,会加载src引入的静态资源,请求方式是GET,而GET方式的请求会经过tomcat,在没有配置tomcat解析请求的解码方式的情况下,默认是ISO-8859-1,然后再经过后台配置的编码过滤器解析时,由于请求已经经过tomcat的解析,编码过滤器再次解析请求地址时,就会出现中文乱码。(编码过滤器对Get提交方式无效)
4. 限制文件格式
CommonsMultipartResolver类在spring-web包下:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
<form action="/Web1/upload.action" method="post" enctype="multipart/form-data"> <input type="file" name="myFile"> <input type="submit" value="上传"> </form> ${msg }
1 @RequestMapping("/file.action") 2 public String file() { 3 return "file"; 4 } 5 6 @RequestMapping("/upload.action") 7 public String upload(MultipartFile myFile, HttpServletRequest req) { 8 String filename = myFile.getOriginalFilename(); 9 //限制只能是.png格式 10 if (!filename.toLowerCase().endsWith(".png")) { 11 req.setAttribute("msg", "格式不符合要求!必须是png格式!"); 12 } else { 13 String realPath = req.getServletContext().getRealPath("/file"); 14 File file = new File(realPath, filename); 15 if (!file.exists()) { 16 file.mkdirs(); 17 } 18 try { 19 myFile.transferTo(file); 20 req.setAttribute("msg", filename); 21 } catch (IllegalStateException e) { 22 e.printStackTrace(); 23 } catch (IOException e) { 24 e.printStackTrace(); 25 } 26 27 } 28 return "file"; 29 }
5. 多文件上传
由于spring框架没有将表单参数封装到myFiles对象上,所以要通过@RequestParam方式指定表单传递的参数封装到myFiles对象上
<form action="/Web1/upload.action" method="post" enctype="multipart/form-data"> <input type="file" name="myFiles"> <input type="file" name="myFiles"> <input type="submit" value="上传"> </form>
1 /** 2 * 多文件上传 3 * 1.表单上放多个file类型的input,并且name值一样 4 * 2.MultipartFile[]类型接收 5 * 3.@RequestParam("myFiles") :myFiles为页面提交的name值 6 */ 7 @RequestMapping("/upload.action") 8 public String upload(@RequestParam("myFiles") MultipartFile[] myFiles, HttpServletRequest req) { 9 10 for (MultipartFile myFile : myFiles) { 11 String filename = myFile.getOriginalFilename(); 12 13 String realPath = req.getServletContext().getRealPath("/file"); 14 File file = new File(realPath, filename); 15 if (!file.exists()) { 16 file.mkdirs(); 17 } 18 try { 19 myFile.transferTo(file); 20 } catch (IllegalStateException e) { 21 e.printStackTrace(); 22 } catch (IOException e) { 23 e.printStackTrace(); 24 } 25 } 26 return "file"; 27 }
6.限制文件上传数据大小
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 设置总上传文件大小 单位是字节 --> <property name="maxUploadSize" value="1024000"></property> </bean>
这样设置的话,若总上传文件大小大于1M,控制台仍然会显示抛出异常,不会影响功能实现,但阻碍了开发者的判断:
严重: Servlet.service() for servlet [springmvc] in context with path [/Web1] threw exception [Request processing failed; nested exception is org.springframework.web.multipart.MaxUploadSizeExceededException: Maximum upload size of 1024000 bytes exceeded; nested exception is org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (3454760) exceeds the configured maximum (1024000)] with root cause org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (3454760) exceeds the configured maximum (1024000)
解决:
解决方法不设置maxUploadSize,自定义拦截对文件的大小进行判断
1 package com.rong.interceptor; 2 3 import javax.servlet.http.HttpServletRequest; 4 import javax.servlet.http.HttpServletResponse; 5 6 import org.apache.commons.fileupload.servlet.ServletFileUpload; 7 import org.apache.commons.fileupload.servlet.ServletRequestContext; 8 import org.springframework.web.multipart.MaxUploadSizeExceededException; 9 import org.springframework.web.servlet.HandlerInterceptor; 10 import org.springframework.web.servlet.ModelAndView; 11 /** 12 * 文件上传拦截器 解决文件超出大小后台异常问题 13 * 14 */ 15 public class UploadInterceptor implements HandlerInterceptor { 16 private int maxUploadSize; 17 //属性依赖注入DI要使用set方法,必须提供 18 public void setMaxUploadSize(int maxUploadSize) { 19 this.maxUploadSize = maxUploadSize; 20 } 21 22 @Override 23 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 24 throws Exception { 25 //判断是否有上传文件 26 if(request!=null&&ServletFileUpload.isMultipartContent(request)){ 27 ServletRequestContext context = new ServletRequestContext(request); 28 long length = context.contentLength(); 29 //int length = request.getContentLength(); 30 System.out.println(length); 31 if(length>this.maxUploadSize){ 32 throw new MaxUploadSizeExceededException(this.maxUploadSize); 33 } 34 } 35 return true; 36 } 37 38 @Override 39 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, 40 ModelAndView modelAndView) throws Exception { 41 } 42 43 @Override 44 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) 45 throws Exception { 46 } 47 48 }
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 设置总上传文件大小 单位是字节 --> <!-- <property name="maxUploadSize" value="1024000"></property> --> <!-- 设置延迟解析为true 才能让自定义异常生效 --> <property name="resolveLazily" value="true"></property> </bean> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/upload.action"/> <bean class="com.rong.interceptor.UploadInterceptor"> <property name="maxUploadSize" value="1024000"></property> </bean> </mvc:interceptor> </mvc:interceptors>
1 @RequestMapping("/upload.action") 2 public String upload(@RequestParam("myFile") MultipartFile myFile, HttpServletRequest req) { 3 String filename = myFile.getOriginalFilename(); 4 String realPath = req.getServletContext().getRealPath("/file"); 5 File file = new File(realPath, filename); 6 if (!file.exists()) { 7 file.mkdirs(); 8 } 9 try { 10 myFile.transferTo(file); 11 } catch (IllegalStateException e) { 12 e.printStackTrace(); 13 } catch (IOException e) { 14 e.printStackTrace(); 15 } 16 return "file"; 17 } 18 19 /** 20 * 自定义异常处理 当发生超过最大上传数的时候,让程序返回上传页面,并提示 21 * 1.返回值类型ModelAndView 参数需要传入Exception或子类 22 * 2.增加ExceptionHandler 23 * 3.设置multipartResolver组件的属性<property name="resolveLazily" value="true"></property> 24 * @param e 25 * @return 26 */ 27 @ExceptionHandler 28 public ModelAndView doException(Exception e){ 29 Map<String,Object> map=new HashMap<>(); 30 if(e instanceof MaxUploadSizeExceededException){ 31 MaxUploadSizeExceededException exception=(MaxUploadSizeExceededException)e; 32 long maxUploadSize = exception.getMaxUploadSize(); 33 map.put("msg", "文件过大!必须小于"+maxUploadSize+"字节!"); 34 }else{ 35 map.put("msg", "系统在忙!"); 36 } 37 return new ModelAndView("file", map); 38 }