文件上传
SpringMVC之上传:
上传:
通过浏览器将客户端硬盘的文件发送给服务器,
并由服务器将该文件存储到其硬盘的一个过程
步骤:
1.在浏览器中选择客户端的硬盘中要上传的文件。
2.点击上传,浏览器以流的形式将文件发送给服务器。
3.服务器接受到请求后,调用对象的Servlet(DispactherServlet)处理请求
在Servlet中完成对request中封存的上传数据解析。解析完成后调用对应的
单元方法,并将解析后的数据传递给单元方法。
--->在Springmvc.xml中配置上传解析bean
4.在单元方法中,将接受到的上传的文件数据存储到服务器硬盘中。
5.将上传记录存储到数据库中(记录ID,文件名,时间,上传人ID)
实现:
1.在浏览器中选择客户端的硬盘中要上传的文件。
在jsp文件中声明一个标签<input type="file"/>
2.点击上传,浏览器以流的形式将文件发送给服务器。
设置form表单数据提交方式为post
设置form表单数据为流数据提交。
设置enctype属性的值
application/x-www-form-urlencoded:表示数据提交为键值对方式
multipart/form-data:表示数据提交为二进制流数据方式
3.在服务器中获取并解析上传数据
导入jar包
配置DispactherServlet
配置springmvc.xml
配置注解扫描
配置注解解析器
配置静态资源放行
配置自定义视图解析器
配置上传解析bean对象(springmvc.xml中)
配置异常跳转bean
4.声明单元方法用来处理上传数据
声明形参接收DispactherServlet解析后的上传数据(形参名及上传数据的键名)
注意:
MultipartFile photo:
MultipartFile类型的形参的值存储了上传文件的所有信息
形参名必须和上传的键名一致。
声明方法体处理上传数据(将上传数据存储到硬盘,将上传记录存储到数据库中)
将上传数据存储到服务器硬盘中
创建动态的文件名
校验文件类型(使用文件后缀名)
校验文件大小(声明在springmvc.xml中的上传解析bean中即可)
获取动态的存储路径
拼接数据存储的绝对路径
调用MultipartFile类中的transferTo方法将数据存储到硬盘中
将上传记录存储到数据库中
用户ID
文件原始名
文件新的名字
文件类型
响应处理结果
jar包
页面表单信息
<form action="upload" method="post" enctype="multipart/form-data">
头像:<input type="file" name="photo"><br>
<input type="submit" value="提交">
</form>
Controller中接收数据
方式一: 指定路径上传到硬盘
方式二: 动态上传到服务器
eclipse部署项目默认是在当前工作空间中集成的tomcat中,路径为:
工作空间路径.metadata.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps
@Controller
public class UserController {
//上传到指定路径
@RequestMapping("/upload")
@ResponseBody
public void fun1(MultipartFile photo) throws IllegalStateException, IOException{
//将上传数据存储到服务器硬盘中
System.out.println("文件名: "+photo.getOriginalFilename());
//getOriginalFilename():获取上传文件的原名
photo.transferTo(new File("d:/tools/"+photo.getOriginalFilename()));
}
//上传到服务器
@RequestMapping("/photo")
public String fun2(MultipartFile photo,HttpServletRequest request) throws IllegalStateException, IOException{
//将上传数据存储到服务器硬盘中
//创建动态的文件名
//获取文件的后缀名 photo.getOriginalFilename() 获取原始文件名
String suffixName = photo.getOriginalFilename().substring(photo.getOriginalFilename().lastIndexOf("."));
System.out.println(suffixName);
//校验文件类型
if(!(".jpg".equals(suffixName)||".png".equals(suffixName)||".bmp".equals(suffixName))){
return "error.jsp";
}
//创建动态的文件
String name = UUID.randomUUID()+""+System.currentTimeMillis();
//拼接新的文件名
String newName = name + suffixName;
//获取动态的存储路径
//动态的获取项目根目录下的绝对路径
String path = request.getServletContext().getRealPath("/imges");
File file = new File(path);
if(!file.exists()){
file.mkdirs();
}
//拼接数据存储的绝对路径
File f = new File(file,newName);
photo.transferTo(f);
//将上传记录存储到数据库记录表中(ID,上传文件原始名,上传文件新名,时间,文件类型)
return "index";
}
}
问题1:
如果DispactherServlet在处理请求时出现异常,我们希望某些指定的异常出现后,跳转到指定的资源,怎么办?
解决:
在springmvc.xml中配置异常跳转bean
问题2:
使用photo.getSize()来对上传文件的大小进行校验,
但是该校验是发生在 解析后的,如何在 解析时 完成大小校验?
解决:
在springmvc.xml中配置上传资源解析bean中声明上传文件大小限制
<!-- 配置指定异常跳转bean -->
<bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<!-- 根据servlet报的错,作为键名来匹配,找上了就跳对应的资源 -->
<prop key="org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException">error.jsp</prop>
</props>
</property>
</bean>
<!-- 配置上传解析bean -->
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver">
<!-- 设置上传文件信息的参数 -->
<property name="defaultEncoding" value="utf-8"></property><!-- 设置解析编码格式 -->
<property name="maxInMemorySize" value="102400000"></property><!-- 设置上传数据的总大小 字节 -->
<property name="maxUploadSize" value="102400"></property><!-- 设置单个文件大小 字节 -->
</bean>
MIME类型(了解)
作用: 规范了浏览器和服务器之间交互的数据的类型
使用:
1.每次浏览器发送给服务器的数据,都是 MIME 类型,说明了发送的数据类型
2.每次服务器响应给浏览器的数据,也会使用 MIME 类型说明响应的数据类型
内容: http://www.w3school.com.cn/media/media_mimeref.asp
文件下载
SpringMVC之下载:
概念:
浏览器发起下载请求,服务器根据请求,将其硬盘中的文件资源读取到代码中。
并将流数据响应给浏览器的过程。
流程:
1.浏览器发起下载请求(要下载文件的服务器存储的文件名)
2.服务器根据请求调用对应的单元方法处理
设置响应文件类型
设置浏览器解析方式
获取要下载的文件的读取流对象
获取输出流对象
读取数据并响应给浏览器
3.响应文件流数据给浏览器
4.浏览器将接收到的流数据直接解析或者另存为
实现:
参照源码
方式一:通用下载实现
@RequestMapping("/download")
public void fun1(HttpServletRequest request,HttpServletResponse response) throws Exception{
File file = new File("D:/tools/dog.jpg");
//设置响应头和客户端保存文件名: 告诉浏览器将接收的流数据另存到客户端,而不是直接解析
response.setCharacterEncoding("utf-8");
response.setContentType("multipart/form-data");
response.setHeader("Content-Disposition", "attachment;fileName=" + file.getName());
//自定义图片名方式
/*String str1 = "虎啊兄弟";
String str2 = new String(str1.getBytes("utf-8"), "iso-8859-1");
response.setHeader("Content-Disposition", "attachment;fileName=" + str2+".jpg");*/
//获取资源存储路径
InputStream in = new FileInputStream(file);
//获取输出流
ServletOutputStream out = response.getOutputStream();
//循环写入
byte[] b = new byte[1024];
int len;
while ((len = in.read(b)) != -1) {
out.write(b,0,len);
out.flush();
}
out.close();
in.close();
}
方式二:基于ResponseEntity实现
//ResponseEnity 返回响应结果的实体对象,里面是个字节数组
@RequestMapping("/ResponseEntity")
public ResponseEntity<byte[]> download(HttpServletResponse response) throws IOException{
File file = new File("D:/tools/dog.jpg");
//设置头部信息
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition", "attchement;filename=" + file.getName());
HttpStatus statusCode = HttpStatus.OK;
//读
InputStream is = new FileInputStream(file);
byte[] b = new byte[is.available()];
is.read(b);
//封装成ResponseEnity,返回
ResponseEntity<byte[]> entity = new ResponseEntity<byte[]>(b,headers,statusCode);
return entity;
}