springMVC的上传和下载
1. 文件上传
上传文件必须将表单的
method
设置为post
,并且将enctype
设置为multipart/form-data
。在
springmvc
中实现文件上传有两种方式:1、使用
Apache Commons FileUpload
元件。2、利用
servlet3.0
及其更高版本的内置支持。
-
MultipartFile
常用方法:
返回参数 | 方法 |
---|---|
byte[] getBytes() |
返回文件的内容作为一个字节数组。 |
String getContentType() |
返回文件的内容类型。 |
InputStream getInputStream() |
返回InputStream读取文件的内容。 |
String getName() |
返回表单中文件组件的名字。 |
String getOriginalFilename() |
返回上传文件的原名 |
long getSize() |
返回文件的大小,以字节byte为单位。 |
boolean isEmpty() |
返回是否上传文件是空的,也就是说,没有文件 选择多部分形式或所选的文件中没有的内容。 |
void transferTo(File dest) |
接收到的文件转移到给定的目标文件。 |
1.1 配置tomcat虚拟路径
编辑
server
文件(%tomcathome%\conf\server.xml)
我们打算建立一个images的虚拟目录,只要在%tomcathome%\conf\server.xml
文件,在标签中加入文件中加入如下代码即可:
注意,此时path一定要写,因为我们此时没有新建xml文件了,所以一定要指明web。
配置文件属性的含义:
docBase
为希望将文件存储到的物理目录的绝对路径。path
为访问文件时的虚拟目录。reloadable
属性的设置有些用处,当reloadable=true
时,相关文件改变,Tomcat先停止webapp
并释放内存,然后重新加载webapp
。这样以来可以省去手工部署web app
工程的时间。和开发工具一起使用可以稍微提高点工作效。
2.使用 Apache Commons FileUpload
元件上传
2.1 添加jar包
commons-fileupload
commons-fileupload
1.3.3
commons-io
commons-io
2.6
2.2 springmvc配置
spring MVC
上下文中没有装配multipartResolver
,不能处理文件上传
bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
10485760
UTF-8
2.3 Controller
@Controller
@RequestMapping(value = "/file")
public class FileUploadController {
@RequestMapping(value = "/{formName}")
public String loginForm(@PathVariable String formName) {
// 动态跳转页面
return "file/" + formName;
}
// 上传文件会自动绑定到MultipartFile中
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public String upload(HttpServletRequest request, @RequestParam("description") String description,
@RequestParam("file") MultipartFile file) throws Exception {
System.out.println(description);
// 如果文件不为空,写入上传路径
if (!file.isEmpty()) {
// 上传文件路径
// String path = request.getServletContext().getRealPath("/images/");
//图片服务器路径
String path = "D:\\QYAPP\\images\\";
// 上传文件名 原始文件名
String filename = file.getOriginalFilename();
//创建新文件,路径为:图片服务器路径+新文件名
File filepath = new File(path, filename);
// 判断路径是否存在,如果不存在就创建一个
if (!filepath.getParentFile().exists()) {
filepath.getParentFile().mkdirs();
}
// 将上传文件保存到一个目标文件当中
file.transferTo(new File(path + File.separator + filename));
return "file/" + "success";
} else {
return "file/" + "error";
}
}
}
2.4 jsp
uploadForm.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
文件上传
文件上传
3. 使用对象接收上传文件
3.1 实体类
public class User implements Serializable{
private String username;
private MultipartFile image;
private String path;
//省略get/set方法
}
3.2 Controller层
@RequestMapping(value="/register")
public String register(HttpServletRequest request,
@ModelAttribute User user,
Model model)throws Exception{
System.out.println(user.getUsername());
// 如果文件不为空,写入上传路径
if(!user.getImage().isEmpty()){
// 上传文件路径
//String path = request.getServletContext().getRealPath("/images/");
//图片服务器路径
String path = "D:\\QYAPP\\images\\";
// 上传文件名
String filename = user.getImage().getOriginalFilename();
File filepath = new File(path,filename);
// 判断路径是否存在,如果不存在就创建一个
if (!filepath.getParentFile().exists()) {
filepath.getParentFile().mkdirs();
}
// 将上传文件保存到一个目标文件当中
user.getImage().transferTo(new File(path+File.separator+ filename));
//虚拟图片路径
String imagePath = request.getRequestURL().toString();
imagePath = imagePath.substring(0, getIndexAtStr(imagePath, "/", 3))+"images"+File.separator+ filename;
System.out.println(imagePath);
user.setPath(imagePath);
// 将用户添加到model
model.addAttribute("user", user);
return "file/" + "userInfo";
}else{
return "file/" + "error";
}
}
/**
* 返回字符出现第num次的位置索引
* @param str 字符串
* @param key 指定字符串
* @param num 在字符串中出现的次数
* @return
*/
public static int getIndexAtStr(String str,String key,int num){
int count = 0;
int index = 0;
while((index=str.indexOf(key,index))!=-1){
//System.out.println("index="+index);
index = index+key.length();//根据在字符串中出现的位置,计数一次,下次从该位置后重新查找出现新的位置
count++;
if(count==num) break;//第几次跳槽循环
}
//return count;
return index;
}
3.3 jsp
3.3.1 registerForm.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
用户注册
用户注册
3.3.2 userInfo.jsp
${requestScope.user.image.originalFilename }
4. Spring MVC 文件下载
页面给出 超链接,
href
的属性等于下载文件的路径,即可下载
springMVC
提供了一个ResponseEntity
类型,可以定义返回的HttpHeaders
和HttpStatus
。
4.1 Controller层
@RequestMapping(value="/download")
public ResponseEntity download(HttpServletRequest request,
@RequestParam("filename") String filename,
Model model)throws Exception{
// 下载文件路径
//String path = request.getServletContext().getRealPath("/images/");
//图片服务器路径
String path = "D:\\QYAPP\\images\\";
File file = new File(path+File.separator+ filename);
HttpHeaders headers = new HttpHeaders();
// 下载显示的文件名,解决中文名称乱码问题
String downloadFielName = new String(filename.getBytes("UTF-8"),"iso-8859-1");
// 通知浏览器以attachment(下载方式)打开图片
headers.setContentDispositionFormData("attachment", downloadFielName);
// application/octet-stream : 二进制流数据(最常见的文件下载)。
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
// 201 HttpStatus.CREATED
return new ResponseEntity(FileUtils.readFileToByteArray(file),
headers, HttpStatus.CREATED);
}
5. 利用servlet3.0及其更高版本的内置支持上传文件
有了
Servlet3
,就不再需要Commons FileUpload
和Commons IO
元件了。在servlet3
及以上版本的容器进行上传文件,处理已上传文件的Servlets
必须以@MultipartConfig
进行标注。下列是可能在MultipartConfig
标注类型中出现的属性,它们都是可选的:
maxFileSize
:上传问件的最大容量,默认值为-1,表示没有限制。大于指定值的文件将遭到拒绝。maxRequestSize
:表示多部分HTTP请求允许的最大容量,默认值为-1。location
:表示在part调用write方法时,要将已上传文件保存的磁盘中的位置。fileSizeThreshold
:上传文件超出这个容量界限时,会被写入磁盘。
5.1 配置web.xml
(1)web.xml
Spring MVC
的DispatcherServlet
处理大部分或所有请求,如果要以@MultipartConfig
进行标注,需要修改源代码。这是不可取的,不过,Servlet3
中有一个比较容易的方法,能使一个servlet
变成一个MultipartConfig Servlet
,即给部署描述符(web.xml
)中的servlet
声明赋值。以下代码与用@MultipartConfig
给DispatcherServlet
进行标注的效果一样。
springmvc
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:springmvc-config.xml
1
20848820
418018841
5.2 springmvc配置
5.3 Controller层(多图上传)
@RequestMapping(value="/multiUpload")
public String multiUpload(HttpServletRequest request, @ModelAttribute User user,//@RequestParam("username") String username,
@RequestParam("files") MultipartFile[] files,
Model model)throws Exception{
/*User user = new User();
user.setUsername(username);*/
List listImagePath=new ArrayList();
/*List files = null;
//得到多部分解析器
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
//判断request是否有文件上传,即多部分
if(multipartResolver.isMultipart(request)){
//转换为多部分request
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
//取得multipartRequest中的所有文件
files = multipartRequest.getFiles("files");
}*/
//虚拟图片路径
String imagePath = request.getRequestURL().toString();
imagePath = imagePath.substring(0, getIndexAtStr(imagePath, "/", 3))+"images/";
/** 图片按类别存储 */
/** 支持多图片上传 */
//if(files != null && files.size() > 0){
if(files != null && files.length>0) {
int i = 0;
//图片服务器路径
String file_path = "D:\\QYAPP\\images\\";
String filename = "jpg";
//根据类别名创建文件夹
File dir = new File(file_path + filename);
if(!dir.exists() || !dir.isDirectory()){
dir.mkdir();
}
for(MultipartFile file : files){
if(file != null && file.getOriginalFilename() != null && file.getOriginalFilename().length()>0){
//原始文件名
String originalFileName = file.getOriginalFilename();
//新文件名,添加原始文件名后缀
String newFileName = UUID.randomUUID() + originalFileName.substring(originalFileName.lastIndexOf("."));
//创建新文件,路径为:图片服务器路径+文件夹名+新文件名
File newFile = new File(file_path + filename + "\\" + newFileName);
//将内存中的数据写入磁盘
file.transferTo(newFile);
i++;
listImagePath.add(imagePath+ filename + "\\" + newFileName);
user.setImage(file);
}
}
// 将用户添加到model
model.addAttribute("listImagePath", listImagePath);
user.setPath(listImagePath.get(0));
model.addAttribute("user", user);
return "file/" + "userInfo";
}else{
return "file/" + "error";
}
}
5.4 jsp
5.4.1 multiUploadForm.jsp
5.4.2 userInfo.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
文件下载
文件下载
${requestScope.user.image.originalFilename }
6.总结:
以上两种方式,在pojo类和
controller
类以及jsp
中的代码并无不同,只是第二种方式需要在web.xml
中对DispatcherServlet
添加multipart-config
标注,并且两种方法在springmvc
中配置的多部分解析器的bean不同。其余代码无需改变。
- 多图上传见 5.3