一、文件的上传与下载
- 上传前提:
- 表单的提交方式必须为post!! enctype必须是"multipart/form-data"--->指示正文内容是使用MIME协议进行描述的
- 必须提供:<input type="file" name="f1"/>
- 对比:enctype="application/x-www-form-urlencoded",正文中的内容是:username=shan&password=123
- 如果enctype的类型是:multipart/form-data,那么传统的request.getParamter(String)会失效
- enctype=multipart/form-data描述正文的方式如下:
- enctype="multipart/form-data"描述正文的方式如下:
- -----------------------------7dc167160938
- Content-Disposition: form-data; name="username"
- admin
- -----------------------------7dc167160938
- Content-Disposition: form-data; name="f1"; filename="C:\Documents and Settings\鐜嬫槶鐝絓妗岄潰\a.txt"
- Content-Type: text/plain MIME类型
- aaaaa
- -----------------------------7dc167160938
- Content-Disposition: form-data; name="f2"; filename="C:\Documents and Settings\鐜嬫槶鐝絓妗岄潰\b.txt"
- Content-Type: text/plain
- bbbbb
- -----------------------------7dc167160938--
- 利用第三方组件进行文件上传(上传步骤)
- 先导入两个jar包:
- 得到DiskFileItemFactory:设置临时目录和缓存大小。可以使用默认的
- DiskFileItemFactory factory = new DiskFileItemFactory();
- 得到ServletFileUpload:文件上传组件(也就是正文解析器)
- ServletFileUpload upload = new ServletFileUpload( factory );
- 判断用户表单是否是 multipart/form-data 类型的?
- boolean isMultipart = upload .isMultipart();
- 是,解析request,得到List<FileItem>
- List<FileItem> items = upload.parseRequest( request );
- 遍历items,判断FileItem,如果是普通字段,打印出来;如果是上传文件,把文件保存到某个目录中.
- 普通字段:由item.getFiledName() 和 item.getString("UTF-8") 获得表单提交的字段名和值.
- 上传文件:通过InputStream和OutputStream流来完成上传,中间还要通过getName()获取文件的路径并正确截取该路径,而且还需要考虑上传文件重名的问题,详述在下
- 先导入两个jar包:
- 上传文件时要考虑的9个问题
- 文件名和表单数据的中文乱码问题?(传统方式已失效)
- 普通字段:通过FileItem的 getString("UTF-8")
- 文件名中文:
- 方式一:request.setCharacterEncoding("UTF-8").
- 方式二:upload.setHeaderEncoding("UTF-8");
- 如何保证服务器的安全?
- 把上传的文件放到用户无法直接访问的地方 WEB-INF
- 文件的重名问题? ====>可以把文件进行改名:保证文件名唯一即可。
- 方式一:当前时间System.currentTime..+"_"+a.txt(乐观主意,同一毫秒值没有传同一资源的用户)
- 方式二:UUID.randomUUID().toString()+"_"+fileName.substring(fileName.indexOf("\\")+1); UUID保证文件名的唯一(推荐)
- 如何防止同一目录下文件太多的问题?
- 分开目录分别存储 images
- 方式一:(乐观主义)2012-11-11/a.txt把每天上传的文件放到一个日期的文件夹中
- 方式二:利用HashCode算法打散存储文件夹,使用二级目录存放:images/dir1/dir2/a.txt
- hashCode算法:
- 0110 0111 1010 1111 0101 0001 1100 1010
- &0xf
- 0000 0000 0000 0000 0000 0000 0000 1111
- -------------------------------------------------
- 0000 0000 0000 0000 0000 0000 0000 1010
- 转换为整数:0~15 16个
- -------------------------------------------------------------------
- 0110 0111 1010 1111 0101 0001 1100 1010
- &0xf0
- 0000 0000 0000 0000 0000 0000 1111 0000
- -------------------------------------------------
- 0000 0000 0000 0000 0000 0000 1100 0000
- >>4
- 0000 0000 0000 0000 0000 0000 0000 1100
- 转换为整数:0~15 16个
- -------------------------------------------------------------------
- 分开目录分别存储 images
- 上传文件的大小控制?及如何友好提示?
- 单个文件的大小控制
- ServletFileUpload的setFileSizeMax(7 * 1024 * 1024);
- 抓住异常(FileUploadBase.FileSizeLimitExceededException),给出友好提示
- 总文件大小控制
- ServletFileUpload的setSizeMax(10 * 1024 * 1024);
- 抓住异常(FileUploadBase.SizeLimitExceededException),给出友好提示
- 单个文件的大小控制
- 超出10k的文件的临时处理?
- fileupload默认情况下不会删除超过10K的临时文件。
- 手工删除:FileItem的delete(); 一定要在流关闭后再删除
- 限制上传文件的类型?
- 方式一:通过判断文件的扩展名来限制文件上传的类型,(不靠谱)
- 方式二:获取上传文件的MIME类型,做限制和过滤
- String type = item.getContentType();
- if(!type.endsWith("image/")
- continue;
- 监听文件的上传进度?
- upload.setProgressListener(new ProgressListener() {
- public void update(long pBytesRead, long pContentLength, int pItems) {
- //应该把该数据通过异步方式传给界面上:JavaScript XMLHttpRequest
- System.out.println("读到了:" +pBytesRead+",文件大小:"+pContentLength+",第几项:"+pItems);
- }
- });
- 用户没有选择上传文件时的问题
- 文件名和表单数据的中文乱码问题?(传统方式已失效)
- HTML的DOM编程:动态添加上传输入域
- 文件的下载
- 监听、事件源、事件(观察者设计模式)
- Servlet规范中的监听器
- 1、如何注册监听器到事件源上
- web.xml
- <listener>
- <listener-class>com.itheima.listener.ServletContextListenerDemo</listener-class>
- </listener>
- 2、
- 监听对象:ServletContext、HttpSession、ServletRequest
- -------------------------------------3个监听器,主要监听他们的创建和销毁
- ServletContextListener
- HttpSessionListener
- ServletRequestListener
- 监听对象:ServletContext、HttpSession、ServletRequest的域(Map)
- -------------------------------------3个监听器,主要监听他们的域中的变化:添加、替换了、删除了
- ServletContextAttributeListener
- HttpSessionAttributeListener:实现在线踢人案例。
- ServletRequestAttributeListener
- public void attributeAdded(ServletContextAttributeEvent scab) {
- 域中来了新同志
- }
- public void attributeRemoved(ServletContextAttributeEvent scab) {
- 同志牺牲了
- }
- public void attributeReplaced(ServletContextAttributeEvent scab) {
- 某个同志被替换了
- }
- 感知型监听器:2个。不需要注册监听器。
- HttpSessionActivationListener:感知自己何时被钝化、何时被活化。
- HttpSessionBindingListener:感知自己何时被HttpSession绑了和解绑了