Live2d Test Env

事件的监听及上传下载

文件上传概述

1.文件上传必须满足的条件:

      a.页面表单的method必须是post

      b.页面表单的enctype必须是multipart/form-data类型的

      c.表单中提供<input type="file">上传文件域    注意:不适合上传特别大的文件;

      

        2.请求正文内容的获取:

         

文件上传原理分析

 1 <%@ page import="java.util.*" pageEncoding="UTF-8"%>
 2 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 3 <html>
 4   <head>
 5     <title>文件上传</title> 
 6     <meta http-equiv="pragma" content="no-cache">
 7     <meta http-equiv="cache-control" content="no-cache">
 8     <meta http-equiv="expires" content="0">    
 9     <!--
10     <link rel="stylesheet" type="text/css" href="styles.css">
11     -->
12 
13   </head>
14   
15   <body>
16       <!-- 
17           enctype="application/x-www-form-urlencoded" 默认值 
18           HTTP协议请求消息头:Content-Type,告知服务器,请求正文的内容的MIME类型(POST方式)
19               Content-Type的默认值:application/x-www-form-urlencoded
20               
21               通过表单的enctype属性,实际上是指定的请求正文的MIME类型
22               
23       -->
24     <form action="${pageContext.request.contextPath}/servlet/UploadServlet3" method="post"
25         enctype="multipart/form-data">
26         姓名:<input type="text" name="name"/><br/>
27         靓照:<input type="file" name="photo"/><br/>
28         靓照:<input type="file" name="photo"/><br/>
29         <input type="submit" value="保存"/>
30     </form>
31   </body>
32 </html>
index.jsp
 1 import java.io.IOException;
 2 
 3 import javax.servlet.ServletException;
 4 import javax.servlet.ServletInputStream;
 5 import javax.servlet.http.HttpServlet;
 6 import javax.servlet.http.HttpServletRequest;
 7 import javax.servlet.http.HttpServletResponse;
 8 
 9 public class UploadServlet1 extends HttpServlet {
10 
11     public void doGet(HttpServletRequest request, HttpServletResponse response)
12             throws ServletException, IOException {
13         ServletInputStream in = request.getInputStream();//获取请求正文的输入流
14         int len = -1;
15         byte b[] = new byte[1024];
16         while((len=in.read(b))!=-1){
17             System.out.println(new String(b,0,len));
18         }
19         in.close();
20         
21     }
22 
23     private void test1(HttpServletRequest request) {
24         /*
25         request.getParameter(String paramName)
26         只能获取请求正文为application/x-www-form-urlencoded类型的数据
27         
28         name=abc&password=123
29         */
30         
31         
32         String name = request.getParameter("name");
33         String photo = request.getParameter("photo");
34         System.out.println("name:"+name);
35         System.out.println("photo:"+photo);//不靠谱
36     }
37 
38     public void doPost(HttpServletRequest request, HttpServletResponse response)
39             throws ServletException, IOException {
40         doGet(request, response);
41     }
42 
43 }
UploadServlet1

          enctype=”multipart/form-data”

        

          可以使用流的方式获取请求正文内容,进一步解析;

借助第三方开发包实现文件上传

  Servlet3.0内部提供对文件上传的支持(需要Tomcat7.0以上) 

    依赖:commons-io

       1、拷贝jar包:

               commons-fileupload-1.2.2.jar 

              commons-io-2.0.1.jar

       2、fileupload组件的解析过程

 

          

          3.主要的类:

               1.DiskFileItemFactory:产生存在磁盘上的FileItem工厂;

                public void setSizeThreshold(int SizeThreshold):设置上传文件时用的缓存大小,默认10KB;

                public void setRepository(File  repository):设置上传文件超出缓存大小的磁盘临时文件存放目录,默认是系统的临时文件存放目录;这里的目录都是服务器的

                    构造方法:DiskFileItemFactory():使用默认缓存,默认临时的文件存放目录

                         DiskFileItemFactory(int  sizeThreshold,File  repository):使用自己制定的缓存和临时文件存放目录;

               2.ServletFileUpload:核心的解析请求类;

               public static final Boolean isMultipartContent(java.servlet.http.HTTPServlet  request);判断用户请求正文是否是multipart/form-data类型;

               public List parseRequest(java.servlet.http.HTTPServletRequest  request):解析请求对象,得到所有的表单输入域(每一个域用FileItem表示);

               3.FileItem:代表每一个表单输入域;

               

              4.上传代码:

            

                 

                 

               

                 

                    

代码撸上

  1 import java.io.File;
  2 import java.io.FileOutputStream;
  3 import java.io.IOException;
  4 import java.io.InputStream;
  5 import java.io.OutputStream;
  6 import java.util.List;
  7 import java.util.UUID;
  8 
  9 import javax.servlet.GenericServlet;
 10 import javax.servlet.ServletException;
 11 import javax.servlet.http.HttpServlet;
 12 import javax.servlet.http.HttpServletRequest;
 13 import javax.servlet.http.HttpServletResponse;
 14 
 15 import org.apache.commons.fileupload.FileItem;
 16 import org.apache.commons.fileupload.FileUploadBase;
 17 import org.apache.commons.fileupload.FileUploadException;
 18 import org.apache.commons.fileupload.ProgressListener;
 19 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
 20 import org.apache.commons.fileupload.servlet.ServletFileUpload;
 21 //借助commons-fileupload实现文件上传:入门案例
 22 public class UploadServlet2 extends HttpServlet {
 23     protected String storeDirectoryRealPath;//存放文件目录的真实路径
 24     //获取初始化参数:上传文件的存放目录
 25     public void init() throws ServletException {
 26         String storeDirectory = "/upload";//默认的存放上传文件的位置
 27         String value = getServletContext().getInitParameter("storeDirectory");
 28         if(value!=null){
 29             storeDirectory = value;
 30         }
 31         //该目录可能不存在
 32             //得到文件的真实路径
 33             storeDirectoryRealPath = getServletContext().getRealPath(storeDirectory);
 34             //判断文件夹是否存在,不存在,创建它
 35             File directory = new File(storeDirectoryRealPath);
 36             if(!directory.exists())
 37                 directory.mkdirs();
 38     }
 39     public void doGet(HttpServletRequest request, HttpServletResponse response)
 40             throws ServletException, IOException {
 41         //判断用户的请求内容是否是mutlipart/form-data类型的
 42         boolean isMultipart = ServletFileUpload.isMultipartContent(request);
 43         if(!isMultipart){
 44             throw new RuntimeException("not a file upload request");
 45         }
 46         try {
 47             //创建DiskFileItemFactory,并设置缓存和临时文件的存放目录
 48             DiskFileItemFactory factory = new DiskFileItemFactory();
 49             
 50             factory.setRepository(new File("d:/"));
 51             
 52             //创建ServletFileUpload, 核心解析类
 53             ServletFileUpload upload = new ServletFileUpload(factory);
 54 //            upload.setProgressListener(new ProgressListener() {
 55 //                /**
 56 //                 * pBytesRead:已经读取的字节数
 57 //                 * pContentLength:总上传文件的大小
 58 //                 * pItems:当前处理的表单项
 59 //                 */
 60 //                public void update(long pBytesRead, long pContentLength, int pItems) {
 61 ////                    double d = (pBytesRead+0.0)/pContentLength;
 62 //                    System.out.println(pBytesRead+">>>"+pContentLength+">>"+pItems);
 63 //                }
 64 //            });
 65             
 66 //            upload.setFileSizeMax(2*1024*1024);//设置单文件大小
 67 //            upload.setSizeMax(3*1024*1024);//设置总文件大小
 68             //得到了List<FileItem>
 69             List<FileItem> items = upload.parseRequest(request);
 70             //遍历:
 71             for(FileItem item:items){
 72                 //遇到普通字段:做出自己的处理
 73                 if(item.isFormField()){
 74                     processFormField(item);
 75                 }else{
 76                 //遇到上传字段:实现文件的上传
 77                     
 78                     String mimeType = item.getContentType();//获取上传输入域的MIME类型
 79                     if(!mimeType.startsWith("image")){
 80                         //日志记录一下
 81                         continue;
 82                     }
 83                     processUploadField(item);
 84                 }
 85             }
 86             response.getWriter().write("上传成功!");
 87         }catch(FileUploadBase.FileSizeLimitExceededException e) {
 88             response.getWriter().write("单文件不能超过2M");
 89         }catch(FileUploadBase.SizeLimitExceededException e){
 90             response.getWriter().write("总文件不能超过3M");
 91         }catch (FileUploadException e) {
 92             e.printStackTrace();
 93             throw new RuntimeException("解析请求内容时遇到了错误");
 94         }
 95         
 96     }
 97     //处理上传文件
 98     protected void processUploadField(FileItem item) {
 99         try {
100             //获取输入流
101 //            InputStream in = item.getInputStream();
102             //得到上传文件的文件名
103             String fileName = getFileName(item.getName());//  浏览:C:\Users\wzhting\Desktop\a.txt   浏览器:a.txt
104             //构建输出流
105 //            OutputStream out = new FileOutputStream(storeDirectoryRealPath+"/"+fileName);
106 //            int len = -1;
107 //            byte b[] = new byte[1024];
108 //            while((len=in.read(b))!=-1){
109 //                out.write(b, 0, len);
110 //            }
111 //            in.close();
112 //            out.close();
113 //            item.delete();//删除临时文件
114             item.write(new File(storeDirectoryRealPath+"/"+fileName));
115             
116         } catch (IOException e) {
117             throw new RuntimeException("读取上传文件出错");
118         }catch(Exception e){
119             throw new RuntimeException("写文件出错");
120         }
121         
122     }
123     /**
124      * 如果文件路径是whole path,截取文件名
125      * @param fileName
126      */
127     protected String getFileName(String fileName) {
128         if(fileName.indexOf("\\")!=-1){
129             fileName = fileName.substring(fileName.lastIndexOf("\\")+1);
130         }
131         return fileName;
132     }
133     //处理普通字段内容
134     protected void processFormField(FileItem item) {
135         String fieldName = item.getFieldName();//普通字段名
136         String fieldValue = item.getString();//普通字段值
137         System.out.println(fieldName+"="+fieldValue);
138     }
139 
140     public void doPost(HttpServletRequest request, HttpServletResponse response)
141             throws ServletException, IOException {
142         doGet(request, response);
143     }
144 
145 }
UploadServlet2
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <web-app version="2.5" 
 3     xmlns="http://java.sun.com/xml/ns/javaee" 
 4     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 5     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
 6     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 7   <display-name></display-name>
 8   <context-param>
 9           <param-name>storeDirectory</param-name>
10         <param-value>/WEB-INF/files</param-value>
11   </context-param>
12   <filter>
13       <filter-name>SetAllCharacterEncodingFilter</filter-name>
14       <filter-class>com.itheima.filter.SetAllCharacterEncodingFilter</filter-class>
15   </filter>
16   <filter-mapping>
17       <filter-name>SetAllCharacterEncodingFilter</filter-name>
18       <url-pattern>/*</url-pattern>
19   </filter-mapping>
20   <servlet>
21     <servlet-name>UploadServlet2</servlet-name>
22     <servlet-class>com.itheima.servlet.UploadServlet2</servlet-class>
23   </servlet>
24   <servlet-mapping>
25     <servlet-name>UploadServlet2</servlet-name>
26     <url-pattern>/servlet/UploadServlet2</url-pattern>
27   </servlet-mapping>
28   <welcome-file-list>
29     <welcome-file>index.jsp</welcome-file>
30   </welcome-file-list>
31 </web-app>
web.xml

文件上传时需要考虑几个问题

1.如何保证服务器安全问题:背景:将jsp文件上传,并访问,会出现安全问题

            解决方案:把存放目录放到WEB-INF目录下;

2.中文乱码问题:

  2.1:普通字段的中文乱码:解决方案:FileItem.getString(encoding):编码要与浏览器的编码一致

  

 

  2.2:上传文件名是中文:解决方案:request.setCharacterEncoding(encoding):通知服务器,请求正文的编码类型

  

3.同一个文件夹下文件同名被覆盖问题:

  1.解决方案:文件名唯一即可;a.txt---->UUID.randomUUID().toString()+"_"+a.txt(filename)

   

4.上传文件分目录存储:

  1.分用户名目录存储:

  2.按照日期分目录存储: 

 1     //按照日期分目录存储文件
 2     protected String getFileName(String fileName) {
 3     String name = super.getFileName(fileName);// a.txt
 4     //按照日期创建目录
 5     Date now = new Date();
 6     DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
 7     String date = df.format(now);
 8     //拼接该目录的真实存放路径
 9     String directoryPath = storeDirectoryRealPath+"/"+date;
10     File directory = new File(directoryPath);
11     if(!directory.exists())
12         directory.mkdirs();
13     
14     return date+"/"+UUID.randomUUID().toString()+"_"+name;
15     }    
View Code 

  3.按照文件名hashCode计算存放目录 (二级目录)

 1     //按照UUID文件名的hashCode计算存放目录
 2     protected String getFileName(String fileName) {
 3         String name = super.getFileName(fileName);// a.txt
 4         String uuidFileName = UUID.randomUUID().toString()+"_"+name;// ae427cfa-4920-418a-992a-59553e54a302_a.txt
 5         
 6         /*
 7         hashCode:
 8             1001 1100 0101 1010 1111 0001
 9             0000 0000 0000 0000 0000 1111  &0xf
10             -----------------------------------
11             0000 0000 0000 0000 0000 0001    取hash码的最低4位:0000~1111 十进制:0~15
12         hashCode:
13             1001 1100 0101 1010 1111 0001
14             0000 0000 0000 0000 1111 0000 &0xf0
15             -----------------------------------
16             0000 0000 0000 0000 1111 0000  取hash码的最低5~8位
17             -----------------------------------
18                         >>4
19             0000 0000 0000 0000 0000 1111:0000~1111 十进制:0~15
20          */
21         
22         int hashCode = uuidFileName.hashCode();
23         int dir1 = hashCode&0xf;//一级目录
24         int dir2 = (hashCode&0xf0)>>4;//二级目录
25         
26         String newPath = dir1+"/"+dir2;
27         String directoryPath = storeDirectoryRealPath+"/"+newPath;
28         File directory = new File(directoryPath);
29         if(!directory.exists())
30             directory.mkdirs();
31         
32         return newPath+"/"+uuidFileName;
33     }
getFileName

5.限制文件的上传大小:

  5.1:限制单个文件的上传大小

  5.2:限制总文件上传大小(多个上传域)

  1 import java.io.File;
  2 import java.io.FileOutputStream;
  3 import java.io.IOException;
  4 import java.io.InputStream;
  5 import java.io.OutputStream;
  6 import java.util.List;
  7 import java.util.UUID;
  8 
  9 import javax.servlet.GenericServlet;
 10 import javax.servlet.ServletException;
 11 import javax.servlet.http.HttpServlet;
 12 import javax.servlet.http.HttpServletRequest;
 13 import javax.servlet.http.HttpServletResponse;
 14 
 15 import org.apache.commons.fileupload.FileItem;
 16 import org.apache.commons.fileupload.FileUploadBase;
 17 import org.apache.commons.fileupload.FileUploadException;
 18 import org.apache.commons.fileupload.ProgressListener;
 19 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
 20 import org.apache.commons.fileupload.servlet.ServletFileUpload;
 21 //借助commons-fileupload实现文件上传:入门案例
 22 public class UploadServlet2 extends HttpServlet {
 23     protected String storeDirectoryRealPath;//存放文件目录的真实路径
 24     //获取初始化参数:上传文件的存放目录
 25     public void init() throws ServletException {
 26         String storeDirectory = "/upload";//默认的存放上传文件的位置
 27         String value = getServletContext().getInitParameter("storeDirectory");
 28         if(value!=null){
 29             storeDirectory = value;
 30         }
 31         //该目录可能不存在
 32             //得到文件的真实路径
 33             storeDirectoryRealPath = getServletContext().getRealPath(storeDirectory);
 34             //判断文件夹是否存在,不存在,创建它
 35             File directory = new File(storeDirectoryRealPath);
 36             if(!directory.exists())
 37                 directory.mkdirs();
 38     }
 39     public void doGet(HttpServletRequest request, HttpServletResponse response)
 40             throws ServletException, IOException {
 41         //判断用户的请求内容是否是mutlipart/form-data类型的
 42         boolean isMultipart = ServletFileUpload.isMultipartContent(request);
 43         if(!isMultipart){
 44             throw new RuntimeException("not a file upload request");
 45         }
 46         try {
 47             //创建DiskFileItemFactory,并设置缓存和临时文件的存放目录(服务器)
 48             DiskFileItemFactory factory = new DiskFileItemFactory();
 49             
 50             factory.setRepository(new File("d:/"));
 51             
 52             //创建ServletFileUpload, 核心解析类
 53             ServletFileUpload upload = new ServletFileUpload(factory);
 54 //            upload.setProgressListener(new ProgressListener() {
 55 //                /**
 56 //                 * pBytesRead:已经读取的字节数
 57 //                 * pContentLength:总上传文件的大小
 58 //                 * pItems:当前处理的表单项
 59 //                 */
 60 //                public void update(long pBytesRead, long pContentLength, int pItems) {
 61 ////                    double d = (pBytesRead+0.0)/pContentLength;
 62 //                    System.out.println(pBytesRead+">>>"+pContentLength+">>"+pItems);
 63 //                }
 64 //            });
 65             
 66 //            upload.setFileSizeMax(2*1024*1024);//设置单文件大小
 67 //            upload.setSizeMax(3*1024*1024);//设置总文件大小
 68             //得到了List<FileItem>
 69             List<FileItem> items = upload.parseRequest(request);
 70             //遍历:
 71             for(FileItem item:items){
 72                 //遇到普通字段:做出自己的处理
 73                 if(item.isFormField()){
 74                     processFormField(item);
 75                 }else{
 76                 //遇到上传字段:实现文件的上传
 77                     
 78                     String mimeType = item.getContentType();//获取上传输入域的MIME类型
 79                     if(!mimeType.startsWith("image")){
 80                         //日志记录一下
 81                         continue;
 82                     }
 83                     processUploadField(item);
 84                 }
 85             }
 86             response.getWriter().write("上传成功!");
 87         }catch(FileUploadBase.FileSizeLimitExceededException e) {
 88             response.getWriter().write("单文件不能超过2M");
 89         }catch(FileUploadBase.SizeLimitExceededException e){
 90             response.getWriter().write("总文件不能超过3M");
 91         }catch (FileUploadException e) {
 92             e.printStackTrace();
 93             throw new RuntimeException("解析请求内容时遇到了错误");
 94         }
 95         
 96     }
 97     //处理上传文件
 98     protected void processUploadField(FileItem item) {
 99         try {
100             //获取输入流
101 //            InputStream in = item.getInputStream();
102             //得到上传文件的文件名
103             String fileName = getFileName(item.getName());//  浏览:C:\Users\wzhting\Desktop\a.txt   浏览器:a.txt
104             //构建输出流
105 //            OutputStream out = new FileOutputStream(storeDirectoryRealPath+"/"+fileName);
106 //            int len = -1;
107 //            byte b[] = new byte[1024];
108 //            while((len=in.read(b))!=-1){
109 //                out.write(b, 0, len);
110 //            }
111 //            in.close();
112 //            out.close();
113 //            item.delete();//删除临时文件
114             item.write(new File(storeDirectoryRealPath+"/"+fileName));
115             
116         } catch (IOException e) {
117             throw new RuntimeException("读取上传文件出错");
118         }catch(Exception e){
119             throw new RuntimeException("写文件出错");
120         }
121         
122     }
123     /**
124      * 如果文件路径是whole path,截取文件名
125      * @param fileName
126      */
127     protected String getFileName(String fileName) {
128         if(fileName.indexOf("\\")!=-1){
129             fileName = fileName.substring(fileName.lastIndexOf("\\")+1);
130         }
131         return fileName;
132     }
133     //处理普通字段内容
134     protected void processFormField(FileItem item) {
135         String fieldName = item.getFieldName();//普通字段名
136         String fieldValue = item.getString();//普通字段值
137         System.out.println(fieldName+"="+fieldValue);
138     }
139 
140     public void doPost(HttpServletRequest request, HttpServletResponse response)
141             throws ServletException, IOException {
142         doGet(request, response);
143     }
144 
145 }
View Code

6.限制文件上传类型:

    MIME类型+文件的扩展名

    只允许上传图片:MIME设置(大类型/小类型)

 

7.临时文件的处理:

  超出缓存会采用磁盘临时文件来缓存

   FileItem.writer():使用该方法处理上传。临时文件会自动清理。(推荐)

  

  手动删除:FileItem.delete();

8.文件上传进度条:(ajax)

  

 

 1 upload.setProgressListener(new ProgressListener() {
 2     /**
 3      * pBytesRead:已经读取的字节数
 4      * pContentLength:总上传文件的大小
 5      * pItems:当前处理的表单项
 6      */
 7     public void update(long pBytesRead, long pContentLength, int pItems) {
 8             double d = (pBytesRead+0.0)/pContentLength;
 9         System.out.println(pBytesRead+">>>"+pContentLength+">>"+pItems);
10     }
11 });
上传进度监听器

 

  

文件的下载

 1 import java.io.IOException;
 2 import java.io.UnsupportedEncodingException;
 3 
 4 import javax.servlet.Filter;
 5 import javax.servlet.FilterChain;
 6 import javax.servlet.FilterConfig;
 7 import javax.servlet.ServletException;
 8 import javax.servlet.ServletRequest;
 9 import javax.servlet.ServletResponse;
10 import javax.servlet.http.HttpServletRequest;
11 import javax.servlet.http.HttpServletRequestWrapper;
12 import javax.servlet.http.HttpServletResponse;
13 //解决GET和POST请求参数和响应输出的编码过滤器
14 public class SetAllCharacterEncodingFilter implements Filter {
15     private FilterConfig filterConfig;
16     public void init(FilterConfig filterConfig) throws ServletException {
17         this.filterConfig = filterConfig;
18     }
19 
20     public void doFilter(ServletRequest req, ServletResponse resp,
21             FilterChain chain) throws IOException, ServletException {
22         HttpServletRequest request;
23         HttpServletResponse response;
24         try{
25             request = (HttpServletRequest)req;
26             response = (HttpServletResponse)resp;
27         }catch(Exception e){
28             throw new RuntimeException("non-http request");
29         }
30         String encoding = "UTF-8";//默认参数
31         String value = filterConfig.getInitParameter("encoding");
32         if(value!=null){
33             encoding = value;
34         }
35         
36         request.setCharacterEncoding(encoding);//POST请求方式
37         response.setCharacterEncoding(encoding);
38         response.setContentType("text/html;charset="+encoding);
39         MyHttpServletRequest mrequest = new MyHttpServletRequest(request);
40         chain.doFilter(mrequest, response);
41     }
42 
43     public void destroy() {
44 
45     }
46 
47 }
48 class MyHttpServletRequest extends HttpServletRequestWrapper{
49     private HttpServletRequest request;
50     public MyHttpServletRequest(HttpServletRequest request){
51         super(request);
52         this.request = request;
53     }
54     public String getParameter(String name) {
55         String value = request.getParameter(name);
56         if(value==null)
57             return value;
58         try {
59             if("get".equalsIgnoreCase(request.getMethod()))
60                 value = new String(value.getBytes("ISO-8859-1"),request.getCharacterEncoding());
61         } catch (UnsupportedEncodingException e) {
62             e.printStackTrace();
63         }
64         return value;
65     }
66     
67 }
编码过滤器
 1 package com.itheima.servlet;
 2 
 3 import java.io.File;
 4 import java.io.UnsupportedEncodingException;
 5 import java.text.DateFormat;
 6 import java.text.SimpleDateFormat;
 7 import java.util.Date;
 8 import java.util.UUID;
 9 
10 import org.apache.commons.fileupload.FileItem;
11 
12 public class UploadServlet3 extends UploadServlet2 {
13     
14     protected void processFormField(FileItem item) {
15         String fieldName = item.getFieldName();//普通字段名
16         String fieldValue;
17         try {
18             fieldValue = item.getString("UTF-8");//普通字段值,指定编码,该编码和浏览器使用的编码要对应
19         System.out.println(fieldName+"="+fieldValue);
20         } catch (UnsupportedEncodingException e) {
21             // TODO Auto-generated catch block
22             e.printStackTrace();
23         }
24     }
25 
26     //按照日期分目录存储文件
27 //    protected String getFileName(String fileName) {
28 //        String name = super.getFileName(fileName);// a.txt
29 //        //按照日期创建目录
30 //        Date now = new Date();
31 //        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
32 //        String date = df.format(now);
33 //        //拼接该目录的真实存放路径
34 //        String directoryPath = storeDirectoryRealPath+"/"+date;
35 //        File directory = new File(directoryPath);
36 //        if(!directory.exists())
37 //            directory.mkdirs();
38 //        
39 //        return date+"/"+UUID.randomUUID().toString()+"_"+name;
40 //    }
41     //按照UUID文件名的hashCode计算存放目录
42     protected String getFileName(String fileName) {
43         String name = super.getFileName(fileName);// a.txt
44         String uuidFileName = UUID.randomUUID().toString()+"_"+name;// ae427cfa-4920-418a-992a-59553e54a302_a.txt
45         
46         /*
47         hashCode:
48             1001 1100 0101 1010 1111 0001
49             0000 0000 0000 0000 0000 1111  &0xf
50             -----------------------------------
51             0000 0000 0000 0000 0000 0001    取hash码的最低4位:0000~1111 十进制:0~15
52         hashCode:
53             1001 1100 0101 1010 1111 0001
54             0000 0000 0000 0000 1111 0000 &0xf0
55             -----------------------------------
56             0000 0000 0000 0000 1111 0000  取hash码的最低5~8位
57             -----------------------------------
58                         >>4
59             0000 0000 0000 0000 0000 1111:0000~1111 十进制:0~15
60          */
61         
62         int hashCode = uuidFileName.hashCode();
63         int dir1 = hashCode&0xf;//一级目录
64         int dir2 = (hashCode&0xf0)>>4;//二级目录
65         
66         String newPath = dir1+"/"+dir2;
67         String directoryPath = storeDirectoryRealPath+"/"+newPath;
68         File directory = new File(directoryPath);
69         if(!directory.exists())
70             directory.mkdirs();
71         
72         return newPath+"/"+uuidFileName;
73     }
74 
75 }
上传文件servlet
 1 package com.itheima.servlet;
 2 
 3 import java.io.File;
 4 import java.io.FileInputStream;
 5 import java.io.IOException;
 6 import java.io.InputStream;
 7 import java.io.OutputStream;
 8 import java.net.URLEncoder;
 9 
10 import javax.servlet.ServletException;
11 import javax.servlet.http.HttpServlet;
12 import javax.servlet.http.HttpServletRequest;
13 import javax.servlet.http.HttpServletResponse;
14 
15 public class DownloadServlet extends HttpServlet {
16 
17     public void doGet(HttpServletRequest request, HttpServletResponse response)
18             throws ServletException, IOException {
19         String uuidfilename = request.getParameter("filename");//get方式,注意编码问题
20         //计算文件所在的目录
21         String storeDirectory = getServletContext().getRealPath("/WEB-INF/files");
22         String path = makeDirs(storeDirectory, uuidfilename);
23         File file = new File(storeDirectory+"\\"+path+"\\"+uuidfilename);
24         if(file.exists()){
25             //通知客户端以下载的方式打开
26             
27             String filename = uuidfilename.substring(uuidfilename.indexOf("_")+1);//获取老文件名  哈里波波.jpg
28             response.setHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode(filename, "UTF-8"));
29             response.setHeader("Content-Type", "application/octet-stream");//通知客户端正文的MIME类型
30             //开始下载
31             InputStream in = new FileInputStream(file);
32             OutputStream out = response.getOutputStream();
33             int len = -1;
34             byte b[] = new byte[1024];
35             while((len=in.read(b))!=-1){
36                 out.write(b, 0, len);
37             }
38             in.close();
39         }else{
40             response.getOutputStream().write("您下载的资源不存在".getBytes("UTF-8"));
41         }
42     }
43 
44     
45     public String makeDirs(String storeDirectoryRealPath,String uuidFilename){
46         int hashCode = uuidFilename.hashCode();
47         int dir1 = hashCode&0xf;//一级目录
48         int dir2 = (hashCode&0xf0)>>4;//二级目录
49         
50         String newPath = dir1+"/"+dir2;
51         String directoryPath = storeDirectoryRealPath+"/"+newPath;
52         File directory = new File(directoryPath);
53         if(!directory.exists())
54             directory.mkdirs();
55         return newPath;
56     }
57     
58     public void doPost(HttpServletRequest request, HttpServletResponse response)
59             throws ServletException, IOException {
60         doGet(request, response);
61     }
62 
63 }
下载servlet
 1 import java.io.File;
 2 import java.io.IOException;
 3 import java.util.HashMap;
 4 import java.util.Map;
 5 
 6 import javax.servlet.ServletException;
 7 import javax.servlet.http.HttpServlet;
 8 import javax.servlet.http.HttpServletRequest;
 9 import javax.servlet.http.HttpServletResponse;
10 //遍历:WEB-INF/files目录下的所有文件。
11 //交给JSP去显示
12 public class ShowAllFilesServlet extends HttpServlet {
13     public void doGet(HttpServletRequest request, HttpServletResponse response)
14             throws ServletException, IOException {
15         Map<String, String> map = new HashMap<String, String>();// key:UUID的文件名  value:老文件名 a.txt
16         //遍历WEB-INF/files下的所有文件,并把文件名放到map中
17         
18         String storeDirectory = getServletContext().getRealPath("/WEB-INF/files");
19         File file = new File(storeDirectory);
20         treeWalk(file,map);
21         
22         //封装参数,交给JSP显示
23         request.setAttribute("map", map);
24         request.getRequestDispatcher("/listFile.jsp").forward(request, response);
25     }
26     //递归遍历,找出所有的文件名称
27     private void treeWalk(File file, Map<String, String> map) {
28         if(file.isFile()){
29             String uuidFileName = file.getName();// UUID_a_a.txt
30             String fileName =uuidFileName.substring(uuidFileName.indexOf("_")+1);//a_a.txt
31             map.put(uuidFileName, fileName);
32         }else{
33             File[] files = file.listFiles();
34             for(File f:files){
35                 treeWalk(f, map);
36             }
37         }
38     }
39 
40     public void doPost(HttpServletRequest request, HttpServletResponse response)
41             throws ServletException, IOException {
42         doGet(request, response);
43     }
44 
45 }
展示所有文件servlet
 1 <%@ page import="java.util.*" pageEncoding="UTF-8"%>
 2 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
 3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 4 <html>
 5   <head>
 6     <title>title</title> 
 7     <meta http-equiv="pragma" content="no-cache">
 8     <meta http-equiv="cache-control" content="no-cache">
 9     <meta http-equiv="expires" content="0">    
10     <!--
11     <link rel="stylesheet" type="text/css" href="styles.css">
12     -->
13 
14   </head>
15   
16   <body>
17     <h1>本站有以下不堪入目的图片</h1>
18     <c:forEach items="${map}" var="me">
19         <c:url value="/servlet/DownloadServlet" var="url">
20             <c:param name="filename" value="${me.key}"></c:param>
21         </c:url>
22         ${me.value}&nbsp;&nbsp;<a href="${url}">下载</a><br/>
23     </c:forEach>
24   </body>
25 </html>
ListFile
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <web-app version="2.5" 
 3     xmlns="http://java.sun.com/xml/ns/javaee" 
 4     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 5     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
 6     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 7   <display-name></display-name>
 8   <context-param>
 9           <param-name>storeDirectory</param-name>
10         <param-value>/WEB-INF/files</param-value>
11   </context-param>
12   <filter>
13       <filter-name>SetAllCharacterEncodingFilter</filter-name>
14       <filter-class>com.itheima.filter.SetAllCharacterEncodingFilter</filter-class>
15   </filter>
16   <filter-mapping>
17       <filter-name>SetAllCharacterEncodingFilter</filter-name>
18       <url-pattern>/*</url-pattern>
19   </filter-mapping>
20   <servlet>
21     <servlet-name>UploadServlet1</servlet-name>
22     <servlet-class>com.itheima.servlet.UploadServlet1</servlet-class>
23     
24   </servlet>
25   <servlet>
26     <servlet-name>UploadServlet2</servlet-name>
27     <servlet-class>com.itheima.servlet.UploadServlet2</servlet-class>
28   </servlet>
29   <servlet>
30     <servlet-name>UploadServlet3</servlet-name>
31     <servlet-class>com.itheima.servlet.UploadServlet3</servlet-class>
32   </servlet>
33   <servlet>
34     <servlet-name>ShowAllFilesServlet</servlet-name>
35     <servlet-class>com.itheima.servlet.ShowAllFilesServlet</servlet-class>
36   </servlet>
37   <servlet>
38     <servlet-name>DownloadServlet</servlet-name>
39     <servlet-class>com.itheima.servlet.DownloadServlet</servlet-class>
40   </servlet>
41 
42 
43 
44 
45 
46   <servlet-mapping>
47     <servlet-name>UploadServlet1</servlet-name>
48     <url-pattern>/servlet/UploadServlet1</url-pattern>
49   </servlet-mapping>
50   <servlet-mapping>
51     <servlet-name>UploadServlet2</servlet-name>
52     <url-pattern>/servlet/UploadServlet2</url-pattern>
53   </servlet-mapping>
54   <servlet-mapping>
55     <servlet-name>UploadServlet3</servlet-name>
56     <url-pattern>/servlet/UploadServlet3</url-pattern>
57   </servlet-mapping>
58   <servlet-mapping>
59     <servlet-name>ShowAllFilesServlet</servlet-name>
60     <url-pattern>/servlet/ShowAllFilesServlet</url-pattern>
61   </servlet-mapping>
62   <servlet-mapping>
63     <servlet-name>DownloadServlet</servlet-name>
64     <url-pattern>/servlet/DownloadServlet</url-pattern>
65   </servlet-mapping>    
66   <welcome-file-list>
67     <welcome-file>index.jsp</welcome-file>
68   </welcome-file-list>
69 </web-app>
web.xml

观察者设计模式(监听器)

1、事件源:发生事件的对象

2、监听器:监听事件源上的发送的事件

3、事件对象:每发生一个事件都会产生一个事件对象,事件对象中封装了事件源

 1 package com.itheima;
 2 //事件源
 3 public class Student {
 4     private String name;
 5     private StudentListener listener;
 6     public Student(String name){
 7         this.name = name;
 8     }
 9     public void sleep(){
10         System.out.println(name+"睡觉");
11     }
12     public void study(){
13         if(listener!=null){//注册了监听器
14             listener.preStudent(new StudentEvent(this));
15         }
16         System.out.println(name+"学习Java编程");
17     }
18     //注册监听器
19     public void addStudentListener(StudentListener listener){
20         this.listener = listener;
21     }
22     public String getName() {
23         return name;
24     }
25     public void setName(String name) {
26         this.name = name;
27     }
28     
29 }
Student
 1 package com.itheima;
 2 
 3 public class StudentDemo {
 4     public static void main(String[] args) {
 5         Student s = new Student("王斐");
 6         
 7         //注册事件监听器
 8         s.addStudentListener(new MyStudentListener());
 9         
10         s.sleep();
11         s.study();
12     }
13 }
14 class MyStudentListener implements StudentListener{
15 
16     public void preStudent(StudentEvent e) {
17         Student s = (Student)e.getSource();
18         String name = s.getName();
19         System.out.println(name+"一定要边学边练,还得做好笔记");
20     }
21 
22     public void preSleep(StudentEvent e) {
23         
24     }
25     
26 }
StudentDemo
 1 package com.itheima;
 2 //事件对象
 3 public class StudentEvent {
 4     private Object source;
 5     public StudentEvent(Object source){
 6         this.source = source;
 7     }
 8     public Object getSource() {
 9         return source;
10     }
11     
12 }
StudentEvent
1 package com.itheima;
2 //监听器
3 public interface StudentListener {
4     void preStudent(StudentEvent e);
5     void preSleep(StudentEvent e);
6 }
StudentListener 

Servlet规范中的八个监听器

7.1监听ServletContext、HttpSession、ServletRequest对象的创建和销毁的监听器

注册监听:web.xml

<listener></listener>

    ServletContextListener

 1 import javax.servlet.ServletContext;
 2 import javax.servlet.ServletContextEvent;
 3 import javax.servlet.ServletContextListener;
 4 /*
 5 非常有用:
 6 ServletContext初始化一次,contextInitialized也就调用一次
 7 完成系统启动时的初始化工作。
 8 
 9 比如:
10 一个配置文件中定义了很多的JavaBean
11 <beans>
12     <bean id="xxDao1" class="XXXDao1Impl"/>
13     <bean id="xxDao2" class="XXXDao2Impl"/>
14     ...
15 </beans>
16 
17 问题:用某个dao。在用dao实例时已经创建好的对象效率要高
18 
19 在启动时,读取xml配置文件,把所有的bean都实例化,并放到内存中。
20 
21 Spring:
22 
23 
24  */
25 public class MyServletContextListener implements ServletContextListener {
26     
27     public void contextInitialized(ServletContextEvent sce) {
28         ServletContext sc = sce.getServletContext();
29         System.out.println("ServletContext对象创建了"+sc);
30     }
31 
32     public void contextDestroyed(ServletContextEvent sce) {
33         ServletContext sc = sce.getServletContext();
34         System.out.println("ServletContext对象销毁了"+sc);
35     }
36 
37 }
MyServletContextListener 

    HttpSessionListener

 1 import javax.servlet.http.HttpSessionEvent;
 2 import javax.servlet.http.HttpSessionListener;
 3 /*
 4 统计当前有多少个客户端在访问
 5  */
 6 public class MyHttpSessionListener implements HttpSessionListener {
 7 
 8     //第一次调用 request.getSession()时
 9     public void sessionCreated(HttpSessionEvent se) {
10         System.out.println(se.getSession()+"创建了一个会话对象");
11     }
12 
13     public void sessionDestroyed(HttpSessionEvent se) {
14         System.out.println(se.getSession()+"会话对象销毁了");
15     }
16 
17 }
MyHttpSessionListener

 

配置Httpsession的过时时间及存放位置:

    ServletRequestListener:统计网站中资源的访问次数:

                            Map<String,Integer>  key:资源的URL,value:访问次数

7.2监听ServletContext、HttpSession、ServletRequest对象中域中数据变化的监听器

  • ServletContextAttributeListener
  • HttpSessionAttributeListener
  • ServletRequestAttributeListener
  •  1 import javax.servlet.ServletContextAttributeEvent;
     2 import javax.servlet.ServletContextAttributeListener;
     3 
     4 public class MyServletContextAttributeListener implements
     5         ServletContextAttributeListener {
     6 
     7     public void attributeAdded(ServletContextAttributeEvent scab) {
     8         System.out.println("添加了新数据");
     9     }
    10 
    11     public void attributeRemoved(ServletContextAttributeEvent scab) {
    12         System.out.println("移除了数据");
    13 
    14     }
    15 
    16     public void attributeReplaced(ServletContextAttributeEvent scab) {
    17         System.out.println("数据被替换了");
    18     }
    19 
    20 }
    MyServletContextAttributeListener

7.3感知型监听器:不需要注册。谁实现了该类型的监听器,就能检测到自身的变化

HttpSessionBindingListener:感知自己何时被绑/解绑HttpSession域中。

HttpSessionActivationListener:感知自己何时随着HttpSession钝化/激活。

踢人案例

查看文件

posted @ 2018-07-20 22:51  麦奇  阅读(590)  评论(0编辑  收藏  举报