文件上传
在web开发中一般会有文件上传的操作
一般JavaWeb开发中文件上传使用的 Apache(阿帕奇)组织的Commons FileUpload组件
SpringMVC中使用 MultipartFile file对象接受上传文件,必须保证 后台参数的名称和表单提交的文件的名称一致
文件上传必须条件
- 表单必须post
- 表单必须有 file 文件域
- 表单的 enctype="multipart/form-data"
后台代码
SpringMVC中使用 MultipartFile file对象接受上传文件,必须保证 后台方法MultipartFile 参数的名称和表单提交的文件的名称一致
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <!-- 配置SpringMVC的前端控制器(总控) --> <servlet> <servlet-name>MVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>MVC</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> </web-app>
springmvc.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd "> <context:component-scan base-package="cn.sxt"></context:component-scan> <!-- 开启SpringMVC的注解驱动 --> <mvc:annotation-driven /> <!-- 配置文件上传解析器:bean的名字是固定的,底层使用的名称注入 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 配置属性,文件大小,内存中最大能保存多少内容 --> <!-- 设置上传文件的最大尺寸为1MB 单位 字节 --> <property name="maxUploadSize" value="#{1024 * 1024}"></property> </bean> </beans>
package cn.sxt; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.UUID; import org.apache.commons.io.FilenameUtils; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.ModelAndView; @Controller public class springmvc { /* * 如果是文件上传,后台使用 MultipartFile 来接受前台对应的文件 * 具体的文件接受使用的 Commons FileUpdate 组件 的实现类 * org.springframework.web.multipart.commons.CommonsMultipartFile * 来完成接受文件上传的 * 注意:前台jsp页面文件域表单的名称必须和后台参数名称一致 * <input type="file" name="headImg"><br> * MultipartFile headImg * * 问题: 什么文件的MIME类型? * 计算机上面所有的文件都有一个类型,这个类型叫做MIME类型 * MIME类型的格式 xxx/xxx * tomcat/conf/web.xml有目前计算机上面所有数据类型的MIME的描述 * 因为Tomcat要进行文件上传,要解析文件类型,所有在web.xml才有这些mieme的配置 * */ @RequestMapping("/upload") public ModelAndView upload(@RequestParam String username,MultipartFile headImg) { System.out.println(username); String name = headImg.getName();//表单名称 <input type="file" name="headImg"> System.out.println(name); String originalFilename = headImg.getOriginalFilename();//文件全名7.jpg System.out.println(originalFilename); /* * 文件的MIME类型 * 判断文件是否是上传的类型 * * */ String contentType = headImg.getContentType(); System.out.println(contentType);//image/jpeg System.out.println(headImg.getSize());//文件大小 //允许文件上传的类型 List<String> asList = Arrays.asList("image/jpeg","image/png"); if(!asList.contains(contentType)) { ModelAndView mo = new ModelAndView(); mo.addObject("erroryMsg","no!!!!!!!!!"); mo.setViewName("/request.jsp"); return mo; } File file = new File("D:/gameproject/b"); //判断文件是否存在,否则创建文件 if(!file.exists()) { file.mkdirs(); } //把用户上传的文件保存的服务器的某一个磁盘位置 //最终把文件名称保存到对应的数据库 try { //使用UUID生成新的随机文件名 String replaceAll = UUID.randomUUID().toString().replaceAll("-", ""); //获取文件名后缀 String extension = FilenameUtils.getExtension(originalFilename); //创建新的文件名称 String newFilename=replaceAll+"."+extension; File file2 = new File(file,newFilename); //保存文件 headImg.transferTo(file2); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } }
多个文件上传:
package cn.sxt; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.UUID; import org.apache.commons.io.FilenameUtils; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.ModelAndView; @Controller public class springmvc { //多个文件上传 @RequestMapping("/uploads") public ModelAndView uploads(MultipartFile[] headImgs) { File file = new File("D:/gameproject/b"); if(!file.exists()) { file.mkdirs(); } for (MultipartFile headImg : headImgs) { //获取文件名称 String filename = headImg.getOriginalFilename(); //把用户上传的文件保存的服务器的某一个磁盘位置 //最终把文件名称保存到对应的数据库 try { //使用UUID生成新的随机文件名 String string = UUID.randomUUID().toString(); //获取文件名后缀 String extension = FilenameUtils.getExtension(filename); //创建新的文件名称 String newFilename=string+"."+extension; File dest = new File(file,newFilename); headImg.transferTo(dest); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return null; } }
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <fieldset> <legend>单个文件上传</legend> <form action="${pageContext.request.contextPath}/upload.do" method="post" enctype="multipart/form-data"> 姓名: <input name="username"><br> 头像: <input type="file" name="headImg"><span style="color:red">${erroryMsg}</span><br> <button type="submit">提交</button> </form> </fieldset> <fieldset> <legend>单个文件上传</legend> <form action="${pageContext.request.contextPath}/uploads.do" method="post" enctype="multipart/form-data"> 文件1: <input type="file" name="headImgs"><br> 文件2: <input type="file" name="headImgs"><br> 文件3: <input type="file" name="headImgs"><br> <button type="submit">提交</button> </form> </fieldset> </body> </html>
题外:文件名称处理
public static void main(String[] args) { //commons-io 包中有一个工具类 FilenameUtils 专门对文件名称处理 String filePath = "d:/updateFile/a/b/c/d/girl.jpg"; System.out.println(FilenameUtils.getBaseName(filePath));//girl System.out.println(FilenameUtils.getExtension(filePath));//jpg System.out.println(FilenameUtils.getName(filePath)); //gril.jp System.out.println(FilenameUtils.getFullPath(filePath)); //d:/updateFile/a/b/c/d/ String uuid = UUID.randomUUID().toString().replaceAll("-", ""); String newFileName = uuid +"."+FilenameUtils.getExtension(filePath); System.out.println(newFileName); }
文件下载
文件下载,SpringMVC并没有做过多的封装,还是使用原来的下载方式
<a href="${pageContext.request.contextPath}/download.do?fileName=我爱.mp4">1111</a> <a href="${pageContext.request.contextPath}/download.do?fileName=1.mp4">1111</a>
package cn.sxt; import java.io.FileInputStream; 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 springmvc { /* * 文件下载思路 * 1.接受前台要下载的资源的名称 * * 2.将对应的资源读取的程序内存中来 * Web开发不适合下载大型文件(几G的电影) * 只适合小型文件 * * 3.使用HttpServletReponse 把文件响应给浏览器(下载) * */ @RequestMapping("/download") public void download(String fileName,HttpServletResponse resp) throws Exception { //0.业务判断 (VIP,积分,充值) System.out.println(fileName); //1.根据文件名把对应的资源读取到内存来形成输入 FileInputStream in = new FileInputStream("D:/gameproject/b/"+fileName); //2.获取文件输出流对象(用于响应数据给浏览器) ServletOutputStream out = resp.getOutputStream(); /* * 浏览器分类 * IE 标准 * W3C 标准 * W3C 标准文件下载时候,响应给浏览器文件名称必须是 ISO-8859-1编码 * * 如果文件名称是中文,接受的时候必须是UTF-8,不然乱码 * * 所以在响应文件给浏览器的时候,我们必须将文件名的字符串编码转换成ISO-8859-1编码进行下载 * 这样就不会出现乱码 * */ //先以UTF-8将字符串转换成字节数组 byte[] bytes = fileName.getBytes("UTF-8"); //再以ISO-8859-1将二进制数组转换成字符串 String string = new String(bytes,"ISO-8859-1"); //响应的内容应该是以附件的形式响应给浏览器(设置响应头) resp.setHeader("Content-Disposition", "attachment;filename="+fileName); /* * 使用 Apache的 commons-io 工具包 * 专门对文件的输入输出进行了封装 * 开发者使用起来非常简单 */ IOUtils.copy(in, out); } }
SpringMVC的拦截器
拦截器 : 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异常信息,记录操作日志,清理资源等)
package cn.sxt.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import cn.sxt.pojo.User; public class CheckLoginInterceptor implements HandlerInterceptor { /* * 在控制器方法执行之前执行 * 返回 true 放行 * 返回 false 不放行 * */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { /* * 拦截思路,从session中获取 共享的 user对象, * 如果有,说明已经登录 * 放行 * 如果对象为null,说明没有登录 * 不放行,跳转到登录让其登录 */ //1.从session获取user对象 User user =(User) request.getSession().getAttribute("user"); if(user == null) { //跳转到登录页面 //request.getRequestDispatcher("/login.jsp").forward(request, response); //重定向 response.sendRedirect(request.getContextPath()+"/login.jsp"); return false; } return true; } //postHandle:控制器方法执行后,视图渲染之前执行(可以加入统一的响应信息). @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // TODO Auto-generated method stub } //afterCompletion:视图渲染之后执行(处理Controller异常信息,记录操作日志,清理资源等 @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // TODO Auto-generated method stub } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd "> <!-- 开启SpringMVC的注解驱动 --> <mvc:annotation-driven /> <!-- 配置SpringMVC对静态资源的处理 --> <mvc:default-servlet-handler /> <!-- 配置视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 前缀 --> <property name="prefix" value="/WEB-INF/view/" /> <!-- 后缀 --> <property name="suffix" value=".jsp" /> </bean> <!-- 配置springMVC的拦截器 --> <mvc:interceptors> <!-- 具体拦截器配置 --> <mvc:interceptor> <!-- 配置拦截的地址 ,只会拦截控制器请求(不会拦截非控制器请求 jsp,html,css,js) /* 只会拦截一级 如 /list.do /delet.do /** 可以拦截多级(两级以及两级以上) /user/list.do /user/delete.do --> <mvc:mapping path="/**" /> <!-- 配置放行的地址 如果放行多个地址 使用 逗号隔开 /xx/a.do,/xxx/b.do,/xxx/c.do --> <mvc:exclude-mapping path="/user/login.do" /> <!-- 拦截器 --> <bean class="cn.sxt.interceptor.CheckLoginInterceptor"></bean> </mvc:interceptor> </mvc:interceptors> </beans>
使用poi组件导出excel文件
使用POI组件实现Excel数据的处理.
1.导包poi
package cn.sxt.test; import java.io.File; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.junit.Test; public class POITest { @Test public void testName() throws Exception { //1.创建一个工作集 HSSFWorkbook book = new HSSFWorkbook(); //2.创建一个Sheet HSSFSheet sheet = book.createSheet(); //3.创建一行,从0开始 HSSFRow createRow = sheet.createRow(0); //3.1创建单元格(列) createRow.createCell(0).setCellValue("姓命"); createRow.createCell(1).setCellValue("年龄"); createRow.createCell(2).setCellValue("性别"); for (int i = 1; i < 10; i++) { //没循环一次创建一行 HSSFRow createRow2 = sheet.createRow(i); //创建列 createRow2.createCell(0).setCellValue("reh命"); createRow2.createCell(1).setCellValue("20"); createRow2.createCell(2).setCellValue("v"); } //同步数据到本地磁盘形成 Excel 文件 book.write(new File("D:/用户信息.xlsx")); } }
使用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<User> 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(); } }
SpringMVC 控制器 Controller的生命周期
Spring 容器创建的对象默认 都是单例 对象
SpringMVC对象 Controller的对象的创建有三种情况
Request : 在用户的一次请求中生效(用户每次请求都会创建Controller对象)多例
Session : Controller对象在一次会话中创建一个对象
如果控制器中有成员变量 设置或者赋值操作,必须使用 request 返回