文件的上传和下载和监听器
知识概要:
1.文件上传的原理和步骤
2.文件的下载的原理和步骤
3.监听器入门和应用
1.文件的上传的原理和步骤
(1)知识扩展
GUID
.全局唯一标识符(GUID,Globally Unique Identifier)也称作 UUID(Universally Unique IDentifier) 。GUID是一种由算法生成的二进制长度为128位的数字标识符
GUID的Java语言的实现
import java.util.UUID; public class guid { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub UUID uuid = UUID.randomUUID(); System.out.println(".{"+uuid.toString()+"}"); } } 另外一种方式 package com.itheima.util;
import java.math.BigInteger; import java.util.Random;
public class GUID { //GUID就是UUID:唯一 public static String generateGUID() { return new BigInteger(165, new Random()).toString(36).toUpperCase(); } } |
(2)文件的上传
1、必要的前提:
a、表单的method必须是post。 b、表单的enctype必须是multipart/form-data enctype的默认值是:application/x-www-form-urlencoded form的enctype属性和请求消息头“Content-Type”作用是一样的,告知服务器请求正文的类型。
(1)application/x-www-form-urlencoded: 请求正文:name=abc&password=123&gender=female
(2) multipart/form-data: 请求正文:
c、表单中提供type=”file”类型的文件上传输入域
2、文件上传的原理 对请求正文是multipart/form-data类型的数据进行解析
3、借助第三方的组件实现文件上传
commons-fileupload 常用的类: DiskFileItemFactory:产生FileItem的工厂类 new DiskFileItemFactory(int sizeThreshold, File repository) sizeThreshold:指定一个缓存大小。默认大小10Kb repository:磁盘临时文件的存放目录。默认是当前用户的系统临时文件目录 new DiskFileItemFactory() ServletFileUpload:核心解析器 FileItem:代表着一个表单上传输入域
import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.List;
import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.io.FilenameUtils; //演示用commons-fileupload进行文件的上传 public class UploadServlet2 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); //构建对象:DiskFileItemFactory DiskFileItemFactory factory = new DiskFileItemFactory(); //判断用户的表单是不是multipart/form-data类型的 boolean isMultipart = ServletFileUpload.isMultipartContent(request); if(!isMultipart){ throw new RuntimeException("没有大脑"); } //创建ServletFileUpload的实例 ServletFileUpload sfu = new ServletFileUpload(factory); //解析请求对象 try { List<FileItem> items = sfu.parseRequest(request); for(FileItem item:items){ if(item.isFormField()){ //普通字段 processFormField(item); }else{ processUploadField(item); } } response.getWriter().write("上传成功"); } catch (FileUploadException e) { throw new RuntimeException("解析请求正文失败,请换一个浏览器试试"); } } //处理上传字段 private void processUploadField(FileItem item) { //把上传文件存到/files目录中 String realPath = getServletContext().getRealPath("/files"); File storeDirectory = new File(realPath); if(!storeDirectory.exists()){ storeDirectory.mkdir(); } //获取文件名 String filename = item.getName();// c:\desktop\a.txt a.txt //filename = filename.substring(filename.lastIndexOf("\\")+1); if(filename!=null){ filename = FilenameUtils.getName(filename); } //上传 try { /* InputStream in = item.getInputStream(); OutputStream out = new FileOutputStream(realPath+"//"+filename); int len = -1; byte b[] = new byte[1024]; while((len=in.read(b))!=-1){ out.write(b, 0, len); } in.close(); out.close(); */ item.write(new File(realPath, filename)); } catch (Exception e) { System.out.println("文件上传失败"); } } //普通表单字段:打印到控制台 private void processFormField(FileItem item) { String fieldName = item.getFieldName(); String fieldValue = item.getString(); System.out.println(fieldName+":"+fieldValue); }
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }
}
|
4、文件上传时需要考虑的几个问题
a、服务器的安全
解决办法:
把上传的文件放到用户无法直接访问的地方(WEB-INF)
限制用户上传文件的类型
b、重名文件被覆盖的问题
解决办法:
让文件名唯一即可。
比如:a.txt---->UUID(GUID)_a.txt
c、避免上传文件都存到一个目录中
方案一:
按日期产生目录,把当天上传的放到该目录中。
方案二:
按照GUID文件名的hash码计算存放目录。
d、中文乱码
普通字段:
FileItem.getString(浏览器用的编码);
中文文件名:
request.setCharacterEncoding(“UTF-8”);//指示
e、限制上传文件的类型
通过判断文件的mime类型和文件的扩展名来限制上传的文件的。
专业做法:获取图片的二进制,找出图片类型的标示二进制代码进行判断。
f、限制上传文件的大小
单个文件大小限制:
ServletFileUpload.setFileSizeMax(long size)
提示:通过抓取异常FileUploadBase.FileSizeLimitExceededException
总文件大小限制:
ServletFileUpload.setSizeMax(long size)
提示:通过抓取异常FileUploadBase.SizeLimitExceededException
g、临时文件的问题
2.文件的下载的原理和步骤
3.监听器的入门和应用
二、Servlet规范中的监听器
1、由Frame的使用说起:观察者设计模式(帮助理解)
2、Servlet规范中的8个监听器
a、监听ServletContext、HttpSession、ServletRequest对象的创建和销毁的监听器。
ServletContextListener:两个
HttpSessionListener:两个
ServletRequestListener:两个
b、监听ServletContext、HttpSession、ServletRequest属性(attribute)变化的监听器
ServletContextAttributeListener:三个 setAttribute(第一次添加,第二次修改)removeAttribute()
HttpSessionAttributeListener:三个
ServletRequestAttributeListener:三个
c、感知型监听器(不需要注册)
HttpSessionBindingListener:实现这个接口类的实例,绑到(解绑)HttpSession域中会被监听到
HttpSessionActivationListener:实现这个接口类的实例,感知自己何时会随着HttpSession对象钝化或激活。
3、监听器案例:统计在线用户,能踢人
看Servlet规范的API