SpringMVC:文件上传及下载
文件上传是项目开发中最常见的功能之一,SringMVC 可以很好地支持文件的上传,但是springmvc上下文中默认没有装配MultipartReseolver,因此默认情况下其不能处理文件上传工作。 如果想使用Springmvc的文件上传功能,则需要在上下文中配置MutilpartResovler。
准备工作
前端表单要求: 为了能上传文件,必须将表达的method设置成post , 并将entcype设置为 multipart/form-data 。 只有这样的情况下 , 浏览器才会把用户的选择的文件已二进制的数据发送给服务器。
对表单中的enctype 属性做个详细的说明:
丶application/x-www=form-urlencoded : 默认方式,只处理表单域中的vale属性值,采用这种编码方式的表单会将表单域中的值处理成url 编码方式。
丶multipart/form-data : 这种编码方式会二进制流的方式来处理表单数据,这种编码方式会把文件域指定文件的内容也封装到请求参数中,不会对字符编码。
丶text/plain:除了把空格转换为 “+” 号外,其他字符都不做编码处理,这种方式适用直接通过表单发送邮件。
<form action="" enctype="multipart/form-data" method="post">
<input type="file" name="file"/>
<input type="submit">
</form>
一旦设置了enctype为multipart/form-data ,浏览器即会采用二进制的方式处理表单数据,而对于上传的处理则涉及在服务器端解析原始的http响应。在2003年,apche Sofatware Foundation发布了开源的Commons FileUploda组件,其很快成为 Servlet/sp 程序上传文件的最佳选择。
、
Servlet3.0规范已经提供方法来 处理文件上传,但这种上传需要在Sevlet中完成。而springMVC则提供了更简单的封装。
Spring mvc 为为文件上传提供了直接的支持,这种支持是用即插即用的MultipartResolver实现的的。Spring mvcApache Commons FileUpload技术实现了一个MultipartResolver实现类:CommonsMultipartResolver。因此,SpringMVC的文件上传还需要依赖Apache Commons FileUpload的组件。
在springmvc-servlet.xml进行配置文件如下:
**注意!!!**这个bena的id必须为:multipartResolver , 否则上传文件会报400的错误!在这里栽过坑,教训!
> <!--文件上传配置-->
> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
> <!-- 请求的编码格式,必须和jSP的pageEncoding属性一致,以便正确读取表单的内容,默认为ISO-8859-1 -->
> <property name="defaultEncoding" value="utf-8"/>
> <!-- 上传文件大小上限,单位为字节(10485760=10M) -->
> <property name="maxUploadSize" value="10485760"/>
> <property name="maxInMemorySize" value="40960"/>
> </bean>
除此之外,我们还需要导入文件上传的jar包,commons-fileupload , Maven会自动帮我们导入他的依赖包 commons-io包;
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
我们会使用它的实现类 CommonsMultipartFile , 常用方法
String getOriginalFilename():获取上传文件的原名
InputStream getInputStream():获取文件流
void transferTo(File dest):将上传文件保存到一个目录文件中
我们去实际测试一下
方式一:采用流的方式上传文件
前端
<form action="/upload" enctype="multipart/form-data" method="post">
<input type="file" name="file"/>
<input type="submit" value="upload">
</form>
Controller
必须加上 @RequestParam , 否则也会报错!作用是用来实现封装!
@RequestMapping("/upload")
public String upload(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
//1.获得文件名
request.setCharacterEncoding("utf-8");
String filename = file.getOriginalFilename();
if ("".equals(filename)){
return "文件不存在";
}
//2.上传文件保存路径
String path = request.getServletContext().getRealPath("/upload");
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();
}
//3.上传文件
InputStream is = file.getInputStream();
FileOutputStream os = new FileOutputStream(new File(realPath, filename));
int len = 0;
byte[] buffer = new byte[1024];
while ((len=is.read(buffer))!=-1){
os.write(buffer,0,len);
os.flush();
}
//4.关闭流
os.close();
is.close();
return "/successful";
}
运行结果:
点击选择文件
选择一个文件,点击提交:
、
ok已经上传成功
实现上传的另一种方式:
//文件上传:CommonsMultipartFile
@RequestMapping(value = "/upload2")
@ResponseBody
public String upload2(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
//上传文件保存路径
String path = request.getServletContext().getRealPath("/upload");
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();
}
//transferTo:将文件写入到磁盘,参数就是一个文件
file.transferTo(new File(realPath+"/"+file.getOriginalFilename()));
return "上传完毕";
}
文件的下载:
在Controller层加入以下代码:
@RequestMapping(value = "/download")
public String download(HttpServletResponse response) throws IOException {
//要下载的图片路径:,服务器有没有强,一般下载都有自己公司的图床,地址;
String path = "C:/Users/Administrator/Desktop";
String filename = "bz.jpg";
//设置响应头信息;【固定的不用记,保存即可】
response.reset(); //让页面不缓存
response.setCharacterEncoding("UTF-8");
response.setContentType("multipart/form-data");//二进制流传输数据
response.setHeader("Content-Disposition","attachment;filename="+URLEncoder.encode(filename,"UTF-8"));
File file = new File(path,filename);
//输入流
FileInputStream input = new FileInputStream(file);
//输出流
ServletOutputStream out = response.getOutputStream();
//执行操作
int len = 0;
byte[] buffer = new byte[1024];
while ((len = input.read(buffer))!=-1){
out.write(buffer,0,len);
out.flush();
}
out.close();
input.close();
return null;
}
indedx.jsp中插入:
<p><a href="${pageContext.request.contextPath}/download">下载图片</a></p>
看下运行结果:
ok完美。