一、简述
一个javaWeb项目中,文件上传功能几乎是必不可少的,本人在项目开发中也时常会遇到,以前也没怎么去理它,今天有空学习了一下这方面的知识,于是便将本人学到的SpringMVC中单文件与多文件上传这部分知识做下笔记。
二、单文件上传
1、页面
这里以一个简单的表单提交为例子,文件上传需要将表单的提交方法设置为post,将enctype的值设置为"multipart/form-data"。
1
2
3
4
|
< form action = "${pageContext.request.contextPath}/test/upload.do" method = "post" enctype = "multipart/form-data" > < input type = "file" name = "img" >< br /> < input type = "submit" name = "提交" > </ form > |
2、控制器
在Controller的处理方法中,使用MultipartFile对象作为参数接收前端上传过来的文件,具体说明请看代码注释。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
@Controller @RequestMapping ( "/test" ) public class MyController { @RequestMapping (value = "/upload.do" , method = RequestMethod.POST) // 这里的MultipartFile对象变量名跟表单中的file类型的input标签的name相同,所以框架会自动用MultipartFile对象来接收上传过来的文件,当然也可以使用@RequestParam("img")指定其对应的参数名称 public String upload(MultipartFile img, HttpSession session) throws Exception { // 如果没有文件上传,MultipartFile也不会为null,可以通过调用getSize()方法获取文件的大小来判断是否有上传文件 if (img.getSize() > 0 ) { // 得到项目在服务器的真实根路径,如:/home/tomcat/webapp/项目名/images String path = session.getServletContext().getRealPath( "images" ); // 得到文件的原始名称,如:美女.png String fileName = img.getOriginalFilename(); // 通过文件的原始名称,可以对上传文件类型做限制,如:只能上传jpg和png的图片文件 if (fileName.endsWith( "jpg" ) || fileName.endsWith( "png" )) { File file = new File(path, fileName); img.transferTo(file); return "/success.jsp" ; } } return "/error.jsp" ; } } |
3、springmvc.xml配置
使用MultipartFile对象接收前端上传过来的文件,还需要在springmvc的配置文件中进行如下配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
<? xml version = "1.0" encoding = "UTF-8" ?> < beans xmlns = "http://www.springframework.org/schema/beans" xmlns:mvc = "http://www.springframework.org/schema/mvc" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns:aop = "http://www.springframework.org/schema/aop" xmlns:tx = "http://www.springframework.org/schema/tx" xmlns:context = "http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> ... <!-- 注意:CommonsMultipartResolver的id是固定不变的,一定是multipartResolver,不可修改 --> < bean id = "multipartResolver" class = "org.springframework.web.multipart.commons.CommonsMultipartResolver" > <!-- 如果上传后出现文件名中文乱码可以使用该属性解决 --> < property name = "defaultEncoding" value = "utf-8" /> <!-- 单位是字节,不设置默认不限制总的上传文件大小,这里设置总的上传文件大小不超过1M(1*1024*1024) --> < property name = "maxUploadSize" value = "1048576" /> <!-- 跟maxUploadSize差不多,不过maxUploadSizePerFile是限制每个上传文件的大小,而maxUploadSize是限制总的上传文件大小 --> < property name = "maxUploadSizePerFile" value = "1048576" /> </ bean > <!-- 设置一个简单的异常解析器,当文件上传超过大小限制时跳转 --> < bean class = "org.springframework.web.servlet.handler.SimpleMappingExceptionResolver" > < property name = "defaultErrorView" value = "/error.jsp" /> </ bean > </ beans > |
上面配置文件中的CommonsMultipartResolver下的属性值配置不是必须的,你也可以全部不写。到这里就可以实现单个文件上传了,下面来看看多文件上传。
三、多文件上传
其实多文件上传也很简单,单文件上传是在Controller的处理方法中使用MultipartFile对象作为参数接收前端上传过来的文件,而多文件上传则使用MultipartFile对象数组来接收。
1、页面
该页面中有几个name值一样的file类型的input标签,其他跟单文件上传的页面没差。
1
2
3
4
5
6
|
< form action = "${pageContext.request.contextPath}/test/upload.do" method = "post" enctype = "multipart/form-data" > file 1 : < input type = "file" name = "imgs" >< br /> file 2 : < input type = "file" name = "imgs" >< br /> file 3 : < input type = "file" name = "imgs" >< br /> < input type = "submit" name = "提交" > </ form > |
2、控制器
控制器中的处理方法使用MultipartFile[]数组作为接收参数,并不能直接使用,需要校正参数,具体说明请看代码注释。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
@Controller @RequestMapping ( "/test" ) public class MyController { @RequestMapping (value = "/upload.do" , method = RequestMethod.POST) // 这里的MultipartFile[] imgs表示前端页面上传过来的多个文件,imgs对应页面中多个file类型的input标签的name,但框架只会将一个文件封装进一个MultipartFile对象, // 并不会将多个文件封装进一个MultipartFile[]数组,直接使用会报[Lorg.springframework.web.multipart.MultipartFile;.<init>()错误, // 所以需要用@RequestParam校正参数(参数名与MultipartFile对象名一致),当然也可以这么写:@RequestParam("imgs") MultipartFile[] files。 public String upload( @RequestParam MultipartFile[] imgs, HttpSession session) throws Exception { for (MultipartFile img : imgs) { if (img.getSize() > 0 ) { String path = session.getServletContext().getRealPath( "images" ); String fileName = img.getOriginalFilename(); if (fileName.endsWith( "jpg" ) || fileName.endsWith( "png" )) { File file = new File(path, fileName); img.transferTo(file); } } } return "/success.jsp" ; } } |
同样的,使用MultipartFile数组接收前端上传过来的多个文件,也需要在springmvc的配置文件进行配置,具体配置与上述单文件上传的springmvc.xml配置没差,直接拷贝过来就行。这样,就可以进行多文件上传了。
四、多种文件上传情景综合
当然,项目开发中,场景可能并不是这么简单,上述的多文件上传是一个个文件选择后一起上传(即多个name相同的input标签),那要是我项目中只要一个input标签就可以一次性多个文件呢?又或者一个页面中既要一个个选择的多文件上传,又要一次性选择的多文件上传,还要有单文件上传呢?没问题,MultipartFile[]通吃,代码也很easy,下面直接上代码。
1、页面
这里的 “一次选择多个文件的多文件上传” 只是在input标签中加上了multiple属性而已。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
< form action = "${pageContext.request.contextPath}/test/upload.do" method = "post" enctype = "multipart/form-data" > 一次选择多个文件的多文件上传 : < br /> < input type = "file" name = "imgs1" multiple>< br /> < br /> 一次选择一个文件的多文件上传 : < br /> < input type = "file" name = "imgs2" >< br /> < input type = "file" name = "imgs2" >< br />< br /> 单文件上传 : < br /> < input type = "file" name = "imgs3" >< br />< br /> < input type = "submit" name = "提交" > </ form > |
2、控制器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
@Controller @RequestMapping ( "/test" ) public class MyController { @RequestMapping (value = "/upload.do" , method = RequestMethod.POST) public String upload( @RequestParam MultipartFile[] imgs1, @RequestParam MultipartFile[] imgs2, @RequestParam MultipartFile[] imgs3, HttpSession session) throws Exception { String path = session.getServletContext().getRealPath( "images" ); for (MultipartFile img : imgs1) { uploadFile(path, img); } for (MultipartFile img : imgs2) { uploadFile(path, img); } for (MultipartFile img : imgs3) { uploadFile(path, img); } return "/success.jsp" ; } private void uploadFile(String path, MultipartFile img) throws IOException { if (img.getSize() > 0 ) { String fileName = img.getOriginalFilename(); if (fileName.endsWith( "jpg" ) || fileName.endsWith( "png" )) { File file = new File(path, fileName); img.transferTo(file); } } } } |
MultipartFile[]就是如此强大,不管单个多个,逻辑处理一样,所以建议在项目开发中使用MultipartFile[]作为文件的接收参数。
五、拓展
1、MultipartFile类常用的一些方法:
1
2
3
4
5
6
7
|
String getContentType() //获取文件MIME类型 InputStream getInputStream() //获取文件流 String getName() //获取表单中文件组件的名字 String getOriginalFilename() //获取上传文件的原名 long getSize() //获取文件的字节大小,单位byte boolean isEmpty() //是否为空 void transferTo(File dest) |
2、CommonsMultipartResolver的属性解析
- defaultEncoding:表示用来解析request请求的默认编码格式,当没有指定的时候根据Servlet规范会使用默认值ISO-8859-1。当request自己指明了它的编码格式的时候就会忽略这里指定的defaultEncoding。
- uploadTempDir:设置上传文件时的临时目录,默认是Servlet容器的临时目录。
- maxUploadSize:设置允许上传的总的最大文件大小,以字节为单位计算。当设为-1时表示无限制,默认是-1。
- maxUploadSizePerFile:跟maxUploadSize差不多,不过maxUploadSizePerFile是限制每个上传文件的大小,而maxUploadSize是限制总的上传文件大小。
- maxInMemorySize:设置在文件上传时允许写到内存中的最大值,以字节为单位计算,默认是10240。
- resolveLazily:为true时,启用推迟文件解析,以便在UploadAction中捕获文件大小异常。
六、注意
- 在开发过程中,建议把配置文件中的异常解析器(SimpleMappingExceptionResolver)先注释掉,方便我们查看错误。
- 有时候上传出错,是因为我们在配置文件中限制了上传文件的大小,你可以不加这个限制,但个人建议这个限制最好还是加上,具体文件大小限制请根据公司项目情况而定。
- SpringMVC中使用MultipartFile接收上传文件需要依赖两个jar包,分别是:commons-fileupload-1.3.3.jar、commons-io-2.5.jar。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://juejin.im/post/594b31da1b69e60062a199fa