在web开发中一般会有文件上传的操作
一般JavaWeb开发中文件上传使用的 Apache组织的Commons FileUpload组件
SpringMVC中使用 MultipartFile file对象接受上传文件,必须保证 后台参数的名称和表单提交的文件的名称一致
文件上传必须条件
表单的 enctype="multipart/form-data"
文件上传是项目开发中最常见的功能之一 ,springMVC 可以很好的支持文件上传,但是SpringMVC上下文中默认没有装配MultipartResolver,因此默认情况下其不能处理文件上传工作。如果想使用Spring的文件上传功能,则需要在上下文中配置MultipartResolver。
前端表单要求:为了能上传文件,必须将表单的method设置为POST,并将enctype设置为multipart/form-data。只有在这样的情况下,浏览器才会把用户选择的文件以二进制数据发送给服务器;
对表单中的 enctype 属性做个详细的说明:
application/x-www=form-urlencoded:默认方式,只处理表单域中的 value 属性值,采用这种编码方式的表单会将表单域中的值处理成 URL 编码方式。
multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定文件的内容也封装到请求参数中,不会对字符编码。
text/plain:除了把空格转换为 "+" 号外,其他字符都不做编码处理,这种方式适用直接通过表单发送邮件。
一旦设置了enctype为multipart/form-data,浏览器即会采用二进制流的方式来处理表单数据,而对于文件上传的处理则涉及在服务器端解析原始的HTTP响应。在2003年,Apache Software Foundation发布了开源的Commons FileUpload组件,其很快成为Servlet/JSP程序员上传文件的最佳选择。
Servlet3.0规范已经提供方法来处理文件上传,但这种上传需要在Servlet中完成。
而Spring MVC则提供了更简单的封装。
Spring MVC为文件上传提供了直接的支持,这种支持是用即插即用的MultipartResolver实现的。
Spring MVC使用Apache Commons FileUpload技术实现了一个MultipartResolver实现类:
CommonsMultipartResolver。因此,SpringMVC的文件上传还需要依赖Apache Commons FileUpload的组件
SpringMVC中使用 MultipartFile file对象接受上传文件,必须保证 后台方法MultipartFile 参数的名称和表单提交的文件的名称一致
//SpringMVC中使用 MultipartFile file对象接受上传文件,必须保证 后台参数的名称和表单提交的文件的名称一致
@RequestMapping("/upload")
public String singleUpload(MultipartFile headImg,@RequestParam("username")String username) throws IOException {
System.out.println(headImg.getName());//获取上传文件的表单名称
System.out.println(headImg.getContentType());//MIME类型
System.out.println(headImg.getSize());//文件大小
System.out.println(headImg.getOriginalFilename());//获取上传文件的完整名称
//获取上传文件对应的输入流
//InputStream in = headImg.getInputStream();
//创建一个磁盘目录用于保存文件
File destFile= new File("c:/upload");
if(!destFile.exists()) {
destFile.mkdir();
}
//使用uuid作为文件随机名称
String fileName = UUID.randomUUID().toString().replaceAll("-", "");
//使用FileNameUtils获取上传文件名的后缀
String extension = FilenameUtils.getExtension(headImg.getOriginalFilename());// jpg , png 等等
//创建新的文件名称
String newFileName = fileName + "."+extension;
//创建要保存文件的File对象
File file = new File(destFile, newFileName);
//保存文件到本地磁盘
headImg.transferTo(file);
return "redirect:/upload.jsp";
}
配置文件上传解析器:bean的名字是固定的
使用spring表达式 #{1024*1024}
@RequestMapping("/uploads")
public String singleUploads(MultipartFile[] headImgs) throws IOException {
//创建一个磁盘目录用于保存文件
File destFile= new File("c:/upload");
if(!destFile.exists()) {
destFile.mkdir();
}
for (int i = 0; i < headImgs.length; i++) {
MultipartFile headImg = headImgs[i];
//使用uuid作为文件随机名称
String fileName = UUID.randomUUID().toString().replaceAll("-", "");
//使用FileNameUtils获取上传文件名的后缀
String extension = FilenameUtils.getExtension(headImg.getOriginalFilename());// jpg , png 等等
//创建新的文件名称
String newFileName = fileName + "."+extension;
//创建要保存文件的File对象
File file = new File(destFile, newFileName);
//保存文件到本地磁盘
try {
headImg.transferTo(file);
} catch (Exception e) {
e.printStackTrace();
}
}
return "redirect:/upload.jsp";
}
文件下载,SpringMVC并没有做过多的封装,还是使用原来的下载方式
package cn.zj.springmvc.controller;
import java.io.FileInputStream;
import java.io.IOException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class DownloadController {
/*
* 下载文件思路
* 1. 接受需要下载文件名称,根据文件名称,找到磁盘对应的文件,读取到内存中形成一个输入流
* 2. 将输入流通过响应对象(HttpServletResponse)响应给浏览器(下载)
*
* 注意:Web一般只会下载小型文件
*
*/
@RequestMapping("/download")
public void upload(String fileName ,HttpServletResponse response) throws IOException {
//0. 判断是否vip,有积分,金豆
//TODO
//1. 接受文件名,读取磁盘对应的文件,创建输入流对象
FileInputStream inputStream = new FileInputStream("C:/"+fileName);
//2.获取响应对象的输出流
ServletOutputStream outputStream = response.getOutputStream();
//3.文件下载文件名的编码使用ISO-08859-1编码
//我们需要将我们UTF-8的 filename转换ISO-8859-1编码
//3.1先将字符串以UTF-8转换成字节数组
byte[] bytes = fileName.getBytes("UTF-8");
//3.2再将字节数组以 ISO-8859-1转换字符串
fileName = new String(bytes, "ISO-8859-1");
//4.响应的内容应该是以附件的形式响应给浏览器(设置响应头)
response.setHeader("Content-Disposition", "attachment;filename="+fileName);
//5.响应文件给浏览器
IOUtils.copy(inputStream, outputStream);
}
}
拦截器 : Interceptor
Spring MVC 的拦截器类似于Servlet 开发中的过滤器Filter,用于对Controller进行预处理和后处理。
使用SpringMVC拦截器步骤:
1)定义拦截器类,实现接口 org.springframework.web.servlet.HandlerInterceptor
2)在applicationContext.xml中配置拦截器
拦截器方法的执行时机:
1):preHandle:控制器方法执行之前执行,返回结果为true表示放行,如果返回为false,表示拦截(可以做权限拦截,登录检查拦截).
2):postHandle:控制器方法执行后,视图渲染之前执行(可以加入统一的响应信息).
3):afterCompletion:视图渲染之后执行(处理Controller异常信息,记录操作日志,清理资源等)
public class CheckLoginInterceptor implements HandlerInterceptor {
//1):preHandle:控制器方法执行之前执行,返回结果为true表示放行,如果返回为false,表示拦截(可以做权限拦截,登录检查拦截).
// true : 放行 false :不放行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("拦截器执行了......");
//从Session中获取登录信息
String username = (String)request.getSession().getAttribute("username");
System.out.println(username);
if(username !=null) {
//放行
return true;
}else {
//跳转到登录页面去
response.sendRedirect(request.getContextPath()+"/login.jsp");
return false;
}
}
//postHandle:控制器方法执行后,视图渲染之前执行(可以加入统一的响应信息).
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
//afterCompletion:视图渲染之后执行(处理Controller异常信息,记录操作日志,清理资源等
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
使用POI组件实现Excel数据的处理.
下载路径:Apache POI - the Java API for Microsoft Documents
//使用POI创建excel文件到本地
@Test
public void testName() throws Exception {
//1.创建数据,用于本地创建excel
HSSFWorkbook book = new HSSFWorkbook();
//2.创建一个sheet 工作区域
HSSFSheet sheet = book.createSheet();
//3.创建一行: 从0开始,代表第一行
HSSFRow row = sheet.createRow(0);
//4.创建一个个单元格
HSSFCell cell1 = row.createCell(0);
//5.设置单元格的数据
cell1.setCellValue("张三");
HSSFCell cell2 = row.createCell(1);
cell2.setCellValue(20);
//将数据保存到本地
try {
book.write(new File("d:/测试.xlsx"));
} catch (Exception e) {
e.printStackTrace();
// TODO: handle exception
}
}
4.2. 使用POI导出数据库的所有用户信息
// 导出用户信息
@RequestMapping("/exprot")
public void export(HttpServletResponse response) {
//创建POI的数据对象
HSSFWorkbook book = new HSSFWorkbook();
//创建sheet
HSSFSheet sheet = book.createSheet();
//创建标题列
HSSFRow titleRow = sheet.createRow(0);
//创建表单单元格并设置值
titleRow.createCell(0).setCellValue("编号");
titleRow.createCell(1).setCellValue("姓名");
titleRow.createCell(2).setCellValue("邮箱");
titleRow.createCell(3).setCellValue("电话");
List users = service.list();
//循环学生
for (int i = 0; i < users.size(); i++) {
//获取每个学生
User user = users.get(i);
//创建学生列
HSSFRow row = sheet.createRow(i+1);
//创建学生信息对应的单元格并设置数据
row.createCell(0).setCellValue(user.getId());
row.createCell(1).setCellValue(user.getName());
row.createCell(2).setCellValue(user.getEmail());
row.createCell(3).setCellValue(user.getPhone());
}
try {
//设置响应头,响应的内容是为附件形式
response.addHeader("Content-Disposition",
"attachment;filename=" + new String("学生信息.xlsx".getBytes(), "ISO-8859-1"));
book.write(response.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
Spring 容器创建的对象默认 都是单例 对象
SpringMVC对象 Controller的对象的创建有三种情况
Request : 在用户的一次请求中生效(用户每次请求都会创建Controller对象)多例
Session : Controller对象在一次会话中创建一个对象
如果控制器中有成员变量 设置或者赋值操作,必须使用 request 返回