文章目录
Day19 监听器&文件上传和下载
tomcat里面的三大组件
- servlet
- filter
- 监听器
监听器(Listener)
事件驱动编程
简单地说就是你点什么按钮(即产生什么事件),电脑执行什么操作(即调用什么函数)。
事件驱动编程中核心对象:
- 事件源:谁发出事件通知,发出消息;也就是事件主体,比如按钮;
- 事件名称:发出什么样的通知的名称,比如鼠标到我头上了,我被别人点了一下;
- 事件响应函数:谁对这个这个事件感兴趣,当这个事件发生时要执行什么样的操作;
- 事件对象:一般来说,当事件发生时,会产生一个描述该事件的具体对象,包含事件相关信息
什么是监听器
监听器就是一个实现特定接口的普通java程序,这个程序专门用于监听一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法将立即被执行。
监听器也可以说是我们WEB中的一个组件
WEB中有哪些监听器
在这里我们分成两类共6个,一类是作用域生命周期监听器,一类是作用域属性监听器。
作用域生命周期监听器
- ServletRequestListener:
- HttpSessionListener:
- ServletContextListener:
作用域属性监听器
- ServletRequestAttributeListener:
- HttpSessionAttributeListener:
- ServletContextAttributeListener
上传功能
上传准备工作
表单控件:<input type=”file” name=”headImg” />
最后想要的肯定是一个二进制的流
重要:上传时,我们表单的请求类型必需设置成enctype=multipart/form-data
上传的method必需是POST的
步骤:
- 准备一个form表单,里面有一个上传,form表单的类型必需是multipart/form-data
- 准备一个上传的Servlet,到后台接收传过来的普通表单数据 与 文件(二进制)
- 导入相应的FileUpload jar包 (commons-fileupload-1.2.2.jar ,commons-io-1.4.jar)
上传代码
StudentUploadServlet:
@WebServlet("/upload")
public class StudentUploadServlet extends HttpServlet{
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.接收请求参数
Map<String, String> map = new HashMap<String, String>();
//调用工具类 完成map里面值的封装
UploadUtil.upload(req, map);
System.out.println(map);
Student student = new Student();
//通过 BeanUtils map 里面的数据拷贝到student
//调用dao的保存方法
//跳转到list页面
}
}
UploadServlet:
private static String[] arr = {"jpg","png","bmp","gif"};
public static void upload(HttpServletRequest req ,Map<String,String> map) throws ServletException, IOException {
//检查我们是否有文件上传请求
boolean isMultipart = ServletFileUpload.isMultipartContent(req);
if (isMultipart) {
try {
//为基于磁盘的文件项创建工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//设置缓存大小
factory.setSizeThreshold(1024 * 10 * 5); //50KB
//设置临时目录 当文件上传完成以后 就会自己删除
factory.setRepository(new File("D:/temp"));
//创建一个新的文件上传处理程序
ServletFileUpload upload = new ServletFileUpload(factory);
//设置上传文件的单个大小
upload.setFileSizeMax(1024 * 1024* 4);
//解析请求
List<FileItem> items = upload.parseRequest(req);
for (FileItem fileItem : items) {
//处理普通字段
if (fileItem.isFormField()) {
//获取字段名字
// System.out.println(fileItem.getFieldName());
//获取字段上面的值
// System.out.println(fileItem.getString());
map.put(fileItem.getFieldName(), fileItem.getString("UTF-8"));
}else {
//fileItem.getName() 获取上传的文件名字
//System.out.println("文件名字:"+fileItem.getName());
/*文件存储的地址盘符不能写死
* 上传到系统的自定义目录
* */
String realPath = req.getServletContext().getRealPath("/upload");
//文件重命名
fileItem.getName();
//获取文件的后缀名
String extension = FilenameUtils.getExtension(fileItem.getName());
List<String> asList = Arrays.asList(arr);
// 如果上传的文件后缀名不在集合里面
if (!asList.contains(extension)) {
//1.抛异常
throw new Exception("请上传图片类型的文件");
//2.给前台提示
}
//自己重新定义一个不会重复的名字 方案1.UUID 2.时间戳
//String filename = UUID.randomUUID().toString();
String filename = String.valueOf(System.currentTimeMillis());
//String filename =System.currentTimeMillis()+"";
map.put(fileItem.getFieldName(), "/upload/"+filename+"."+extension);
//处理文件
File fileupload = new File(realPath,filename+"."+extension);
//判断文件夹是否存在
if (!fileupload.getParentFile().exists()) {
//如果有不存在的文件夹,就创建文件夹
fileupload.getParentFile().mkdirs();
}
//把上传的数据写到指定的文件中
fileItem.write(fileupload);
}
}
} catch (FileUploadBase.FileSizeLimitExceededException e) {
//如果文件过大 单独处理 --可以去自定义一个异常 告诉用户文件过大 --给前台提示 当前上传的文件过大
} catch (Exception e) {
e.printStackTrace();
}
}
}
上传细节处理
- IE低版本的文件名称Bug解决
- 上传文件的名称冲突问题
- 将文件存在本项目中
- 普通字段的获取
- 设置缓存大小与临时目录
- 设置文件大小
在上述代码中体现
下载功能
<a href="/download/aa.rar">aa.rar</a><br />
<a href="/download/美女.rar">美女.rar</a><br />
<a href="/download/用户.rar">用户.rar</a><br />
神奇的事情发生了! 直接就可以下载! 简单得大家都不敢相信。
行了,这种下载方式在一些网站中也在使用,但是它有相应的问题:
第一:如果你的文件是一个图片,它是不会下载的,因为浏览器对于它自己认识的文件会去尝试打开(听说IE低版本(IE6)连压缩文件都要尝试一下)
第二:现在大家上过很多论坛什么的,咱们下载文件还需要判断用户是否登录,有的时候还会进行相应的扣分吧!这个下载方式也没有办法实现
好处:简单,没有中文乱码问题
重要!!!
//设置响应的文件类型
//告诉浏览器文件应该被下载,而不是被直接打开(IE6直接打开)
// text/html;charset=utf-8
resp.setContentType("application/x-msdownload");
// 两个参数:第一个参数相当于拿到程序中的真实文件 第二个参数拿到我们的响应输出流 然后通过流将文件从程序拷备到客户端
Files.copy(Paths.get(file.getAbsolutePath()), resp.getOutputStream());