文章目录
1、上传单个文件
1.1 导入文件上传依赖jar包
Spring MVC实现文件上传,需要再添加两个jar包。一个是文件上传的jar包,一个是其所依赖的IO包。这两个jar包,均在Spring支持的org.apache.commons中。具体jar包如下:
1.2 创建上传页面
在WEB-INF/jsp下创建名为“upload”的文件夹用来存放文件上传页面,在该文件夹下创建名为“upload.jsp”的具有文件上传功能的JSP页面。其表单的设置需要注意,method属性为POST,enctype属性为multipart/form-data。另外,需要注意file表单元素的参数名称,Controller中需要使用,具体代码如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>文件上传</title>
</head>
<body>
<h1>单文件上传演示案例</h1>
<form action="doUploadSingle.action" method="post" enctype="multipart/form-data">
请选择上传的图片:<input type="file" name="photo" /><br/>
<input type="submit" value="上传单个文件" />
</form>
</body>
</html>
1.3 定义处理器(Controller)
提前在“out/artifacts/SSMLearn_war_exploded/”路径下创建名为“images”的文件夹用来保存上传到服务器上的图片。路径如下图所示:
然后,在“com.ccff.controller”下创建名为“UploadController”的控制器。具体代码如下所示:
package com.ccff.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
@Controller
@RequestMapping("/UploadTest")
public class UploadController {
@RequestMapping("/upload")
public String upload(){
return "upload/upload";
}
@RequestMapping("/doUploadSingle")
public String doUploadSingle(MultipartFile photo, HttpServletRequest request, Model model) throws IOException {
if (!photo.isEmpty()){
//服务端的images目录需要手动先创建好
String path = request.getServletContext().getRealPath("/images");
//获取原始文件名
String fileName = photo.getOriginalFilename();
//新的图片名称(UUID的随机名称)
String newFileName = UUID.randomUUID() + "-" + fileName;
//限制文件上传类型
if (fileName.endsWith(".jpg") || fileName.endsWith(".png") || fileName.endsWith("gif")){
File file = new File(path,newFileName);
//完成上传
photo.transferTo(file);
//图片回显
model.addAttribute("fileName",newFileName);
}else {
return "upload/fail";
}
}
return "upload/success";
}
}
用于接收表单元素所提交参数的处理器方法的形参类型不是File,而是MultipartFile。MultipartFile为一个接口,专门用于处理文件上传问题。该类型参数的名称为映射前端上传页面的图片资源input标签的name属性。在Spring MVC中,MultipartFile类主要用来接收并转换request请求中multipart类型的文件数据。执行Controller获得MultipartFile类型的参数后,就可以使用该参数进行文件处理了。
MultipartFile类常用的方法如下表所示:
方法名 | 返回值 | 释义 |
---|---|---|
getContentType() | String | 获取文件MIME类型 |
getInputStream() | InputStream | 获取文件流 |
getName() | String | 获取form表单中文件组件的名字 |
getOriginalFilename() | String | 获取上传文件的原名 |
getSize() | long | 获取文件的大小,单位为byte |
isEmpty() | boolean | 是否为空 |
transferTo(File dest) | void | 将数据保存到一个目标文件中 |
1.4 注册文件上传处理器
使用Spring MVC上传文件,需要在类加载配置文件springmvc.xml中配置multipart类型解析器(即MultipartFile接口的实现类CommonsMultipartResolver)。要求该bean的id必须为multipartResolver。 具体配置信息如下:
<!--注册multipart解析器,这个id名字固定,是由DispatcherServlet直接调用的-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="utf-8" />
<property name="maxUploadSize" value="1048576" />
</bean>
该Bean是由中央调度器(DispatcherServlet)执行处理器映射器RequestMapping之前加载调用进行判断的。如果容器中定义了名为multipartResolver的Bean,且请求也为multipart类型(即enctype属性值为multipart/form-data),则返回MultipartHttpServletRequest请求类型,完成文件上传功能。否则,返回普通的HttpServletRequest请求类型。
对于文件名为中文的文件,默认情况下上传完成后,文件名为乱码,因为默认情况下文件上传处理器使用的字符集为ISO-8859-1。可以他通过设置属性defaultEncoding来指定文件上传所使用的字符集。
MultipartFile接口的实现类CommonsMultipartResolver继承自CommonsFileUploadSupport类,而该类有一个属性maxUploadSize可以用来限制上传文件的大小,单位字节B。如果不对属性进行设置,或指定其值为-1,则表示不对文件上传大小做限制。这里需要注意的是,该大小为上传文件的总大小。即,多个上传文件大小之和不能大于该设定值。
当然,也可通过设置属性maxUploadSizePerFile,再添加对每个上传文件的大小设置。即每个文件的大小不能超过maxUploadSizePerFile指定值,而文件大小综合也不能超过maxUploadSize指定值。
1.5 创建结果页面
在“WEB-INF/jsp/upload”下创建名为“success.jsp”的JSP页面用来提示文件上传成功,并且回显上传的图片。创建名为“fail.jsp”的JSP页面用来提示文件上传失败。
success.jsp具体代码如下所示:
<%@ page import="java.net.URLEncoder" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page pageEncoding="UTF-8" %>
<html>
<head>
<title>上传成功</title>
</head>
<body>
<h1>上传成功!</h1>
<c:if test="${fileName != null}">
${fileName}:<br/><img src="/demo/images/${fileName}">
</c:if>
</body>
</html>
fali.jsp具体代码如下所示:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>上传失败</title>
</head>
<body>
<h1>上传失败!</h1>
</body>
</html>
1.6 测试结果
将项目部署到Tomcat上后,在浏览器内输入请求URL:http://localhost:8080/demo/UploadTest/upload.action 后显示文件上传页面(upload.jsp)如下所示:
选择一张图片进行上传,如下所示:
点击上传按钮提交表单后,将该表单提交给Controller中的doUploadSingle方法处理,上传文件并显示结果如下:
1.7 解决中文图片名回显问题
仔细回顾我们会发现,第一次我们测试的时候上传的图片的图片名称为英文,接下来我们上传一张图片名称含有中文的图片再次测试,当上传如下图片时:
点击上传按钮提交表单后我们会发现,文件上传虽然成功,但是上传后的图片无法回显在页面中,结果如下:
此时当我们查看网页源代码的时候也发现,路径应该也是没有问题的,具体显示如下:
该问题就出现在源文件中img标签中的src属性中的图片的名字中存在中文。导致该问题的原因是当加载该网页的时候浏览器还会再发送一次get请求到Tomcat服务器来加载img标签中的图片,而一般浏览器默认用的发送编码为UTF-8,Tomcat服务器的http Connector所用的URI解码默认用的是 ISO-8859-1,由于两个编码方式不一样,这里就出现了问题。
经过多方位了查找资料,最靠谱的方式就是修改Tomcat服务器的配置文件server.xml,找到如下代码段:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
将其修改为如下所示,其中URIEncoding=“UTF-8” 这项,其含义是指定URI的编码为:UTF-8。在后面加上这一项,重启Tomcat服务器后问题就可以解决了。
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" URIEncoding="utf-8" />
再次上传含有中文的图片,此时显示成功。
2、上传多个文件
2.1 修改文件上传页面(upload.jsp)
在之前上传单个文件的基础上,修改upload.jsp页面,使得其能够显示上传多个文件的表单,具体代码如下所示:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>文件上传</title>
</head>
<body>
<h1>单文件上传演示案例</h1>
<form action="doUploadSingle.action" method="post" enctype="multipart/form-data">
请选择上传的图片:<input type="file" name="photo" /><br/><br/>
<input type="submit" value="上传单个文件" />
</form>
<br/>
<hr>
<br/>
<h1>多文件上传演示案例</h1>
<form action="doUploadMore.action" method="post" enctype="multipart/form-data">
请选择需要上传的图片1:<input type="file" name="images" /><br/>
请选择需要上传的图片2:<input type="file" name="images" /><br/>
请选择需要上传的图片3:<input type="file" name="images" /><br/><br/>
<input type="submit" value="上传多个文件" />
</form>
</body>
</html>
2.2 修改控制器(Controller)
在原有的控制器(Controller)的基础上增加doUploadMore方法,用来处理多文件上传。这里需要注意的是,处理多文件的上传与处理单文件的上传的不同之处在于MultipartFile类型参数。单文件为一个MultipartFile类型参数,而多文件为一个MultipartFile类型的数组。由于Controller并不能直接自动转成MultipartFile类型的数组,因此需要利用@RequestParam注解对其进行参数校正,该注解不能省略。 添加的doUploadMore方法具体代码如下所示:
/**
* 实现过个文件上传
* @param images
* @param request
* @param model
* @return
* @throws IOException
*/
@RequestMapping("/doUploadMore")
public String doUploadMore(@RequestParam MultipartFile[] images, HttpServletRequest request, Model model) throws IOException {
//服务端的images目录需要手动先创建好
String path = request.getServletContext().getRealPath("/images");
List<String> fileNames = new ArrayList<>();
for (MultipartFile photo : images){
if (!photo.isEmpty()){
//获取原始文件名
String fileName = photo.getOriginalFilename();
//新的图片名称(UUID的随机名称)
String newFileName = UUID.randomUUID() + "-" + fileName;
//限制文件上传类型
if (fileName.endsWith(".jpg") || fileName.endsWith(".png") || fileName.endsWith("gif")){
File file = new File(path,newFileName);
//完成上传
photo.transferTo(file);
fileNames.add(newFileName);
}else {
return "upload/fail";
}
}
}
if (fileNames.size() > 0){
model.addAttribute("fileNames",fileNames);
}
return "upload/success";
}
2.3 修改上传成功页面(success.jsp)
修改原有的success.jsp,使其能够显示多文件上传成功后的提示信息并回显上传的图片,具体修改如下:
<%@ page import="java.net.URLEncoder" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page pageEncoding="UTF-8" %>
<html>
<head>
<title>上传成功</title>
</head>
<body>
<c:if test="${fileName != null}">
<h1>单个文件上传成功!</h1>
${fileName}:<br/><img src="/demo/images/${fileName}">
</c:if>
<c:if test="${fileName != null} && ${fileNames != null}">
<br/>
<hr/>
<br/>
</c:if>
<c:if test="${fileNames != null}">
<h1>多个文件上传成功!</h1>
<c:forEach items="${fileNames}" var="fileName">
${fileName}:<br/><img src="/demo/images/${fileName}"><br/>
</c:forEach>
</c:if>
</body>
</html>
2.4 测试结果
将项目重新部署到Tomcat上后,在浏览器内输入如下请求URL:http://localhost:8080/demo/UploadTest/upload.action 后显示如下界面:
直接在多文件上传演示案例处选择三张图片进行上传,如下所示:
当点击上传按钮后将表单提交给Controller中的doUploadMore方法进行多文件上传的处理,当文件上传成功后会显示提示信息,并回显上传成功的图片,结果如下:
3、文件下载
文件下载比较简单,直接在页面中给出一个超链接,该链接href的属性等于要下载文件的文件名,就可以实现文件下载了。但是如果该文件的文件名为中文文件名,在某些早期的浏览器上就会导致下载失败;如果使用最新的Firefox、Opera、Chrome、Safari则都可以正常下载文件名为中文的文件了。
Spring MVC提供了一个ResponseEntity类型,使用它可以很方便地定义返回的HttpHeaders和HttpStatus。
首先,在“WEB-INF/jsp/upload”下创建名为“download.jsp”的JSP页面用于展示下载页。具体代码如下所示:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>下载</title>
</head>
<body>
<h1>文件下载</h1>
<br/>
<a href="doDownLoad/40044eab-62a8-4363-8716-a29fc1b508c6-timg (2).jpg">反正是一张图片,你就不想下载下来看一眼吗?</a>
</body>
</html>
然后,在UploadController控制器类中添加download方法和doDownLoad方法。其中,download方法用于展示下载页面,doDownLoad方法用于处理下载逻辑。具体代码如下所示:
/**
* 显示文件下载页面
* @return
*/
@RequestMapping("/download")
public String download(){
return "upload/download";
}
/**
* 实现文件下载
* @param request
* @param filename
* @return
* @throws IOException
*/
@RequestMapping(value = "/doDownLoad/{filename}", method = {RequestMethod.GET})
public ResponseEntity<byte[]> doDownLoad(HttpServletRequest request, @PathVariable("filename") String filename) throws IOException {
//下载文件路径
String path = request.getServletContext().getRealPath("/images/");
System.out.println(path+"\\"+filename+".jpg");
File file = new File(path+"\\"+filename+".jpg");
HttpHeaders headers = new HttpHeaders();
//下载显示的文件名,解决中文名称乱码问题
String downliadFileName = new String(filename.getBytes("UTF-8"),"iso-8859-1");
//通知浏览器以attachment(下载方式)打开图片
headers.setContentDispositionFormData("attachment",downliadFileName);
//application/octet-stream:二进制流数据(最常见的文件下载)
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
//201 HttpStatus.CREATED
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers,HttpStatus.CREATED);
}
doDownLoad方法接收到页面传递的文件名filename后,使用Apache Commons FileUpload组件的FileUtils读取项目的images文件夹下的该文件,并将其构建成ResponseEntity对象返回客户端下载。
使用ResponseEntity对象,可以很方便地定义返回的HttpHeaders和HttpStatus。上面代码中的MediaType,代表的是Internet Media Type,即互联网媒体类型,也叫做MIME类型。在Http协议消息头中,使用Content-Type来表示具体请求中的媒体类型信息。HttpStatus类型代表的是Http协议中的状态。有关MediaType和HttpStatus类的详细信息请参考Spring MVC的API文档。
最后,将项目重新部署到Tomcat上后,在浏览器内输入请求URL:http://localhost:8080/demo/UploadTest/download 后即可显示下载页面,如下所示:
当点击超链接后,跳出下载提示界面,选择下载地址,保存,完成下载即可。