## 文件上传和下载 ##
**增强HttpServletRequest对象**
1.装饰者模式
* 需求:Connection的接口(SUN公司提供的),实现类是数据库的生成商提供的实现类。增强MySQL提供Connection接口的实现类。(不知道实现叫什么名字)
* Connection conn = ..... SUN提供的
* 使用的MySQL的数据库(导入驱动包:包含Connection接口的实现类 MySQLConnection )
class MySQLConnection implements Connection{
public Statement createStatement(){
// 实现完成了
}
public void close(){
// MySQL的实现类也实现了该方法 销毁链接
}
}
* 装饰者的模式 是你还有你,一切拜托你
// 是你
class MyConnection implements Connection{
// 还有你
private Connection conn;
public MyConnection(Connection conn){
this.conn = conn;
}
// 一切拜托你
public Statement createStatement(){
// 调用MySQLConnection中的createStatement()方法
return conn.createStatement();
}
// 增强该方法
public void close(){
// MySQL的实现类也实现了该方法 销毁链接
// conn.close();
// 自己写
归还链接
}
...
}
MyConnecton con = new MyConnection(new MySQLConnection());
con.createStatement(); -- 相当于 MySQLConnection.createStatement();
2.request.getParameter("username");解决该方法中文乱码的问题。
* 分析怎么做?装饰者增强
HttpServletRequest 接口-- 谁提供的(SUN公司提供的)
Tomcat服务器访问Servlet的时候,服务器创建了两个对象(request,response)服务器提交的实现类。
class TomcatRequest implements HttpServletRequest{
publiuc String getParameter(String name){
// 实现获取参数的值
return "";
}
...
...
}
HttpServletRequestWrapper类底层实现原理:
class HttpServletRequestWrapper implements HttpServletRequest{
private HttpServletRequest request;
public HttpServletRequestWrapper(HttpServletRequest request){
this.request = request;
}
// 空实现
publiuc String getParameter(String name){
// 自己逻辑
return request.getParameter(name);
}
public String getQueryString(){
return request.getQueryString();
}
public String getQueryString(){
return request.getQueryString();
}
public String getQueryString(){
return request.getQueryString();
}
...
...
...
...
}
* SUN公司提供了一个类HttpServletRequestWrapper类
* 自己编写一个类,继承HttpServletRequestWrapper,只需要关注增强的方法。
**文件上传的概述和原理**
1.文件上传概述:客户端(需要文件的输入项),服务器:把本地的文件保存到服务器端。
2.百度网盘 上传图片
3.想在JavaWeb阶段实现文件上传
* 客户端
* <input type="file">
* 做文件上传的三点注意事项:
* 需要一个表单,method属性必须是post
* <input type="file" name="myfile" > name必须指定。
* 表单上有一个属性:enctype=multipart/form-data
* 服务器端
* IO的读写操作
**Fileupload组件(文件上传组件)**
1.JSPSmartUpload -- 文件上传的组件(不写,过时了)。适合Model1时代
2.FileUpload组件 -- 适合Model2时代,把提交到Servlet里面,可以做文件上传。
3.导入jar包。
* 到入两个jar包。
* commons-fileupload-1.2.1.jar
* commons-io-1.4.jar
4.编写文件上传
**文件上传的入门**
1.第一步:编写客户端(提交方式是post,file的name属性必须指定,enctype="multipart/form-data")
2.第二步:编写后台程序
如果是普通的文本项:
fileItem.isFormField()
获取name的名称: fileItem.getFieldName();
获取用户输入的值: fileItem.getString("UTF-8")
如果是文件上传项:
先获取文件的名称: fileItem.getName();
获取文件的输入流: fileItem.getInputStream()
**说一些问题**
1.在文件上传时,传统request.getParameter()获取不到内容
只能用:
String name = fileItem.getFieldName();
// 获取用户输入的值
String value = fileItem.getString();
2.如果你使用IE6浏览器,上传文件的代码有问题。
* 如果使用的IE6,获取文件的内容:d:/aa/boy3.jpg
**FileUpload核心类**
**DiskFileItemFactory类**
1.DiskFileItemFactory类 -- 磁盘文件项工厂类
2.方法
* DiskFileItemFactory()
* DiskFileItemFactory(int sizeThreshold, java.io.File repository)
* sizeThreshold : 设置缓冲区的大小,默认值是10K
* repository : 如果缓冲区大小小于上传文件的大小,产生临时文件,临时文件保存repository目录下。
* void setSizeThreshold(int sizeThreshold) -- 设置缓冲区的大小
* void setRepository(java.io.File repository) -- 设置临时文件存放位置
**ServletFileUpload类**
1.方法:
* static boolean isMultipartContent(javax.servlet.http.HttpServletRequest request) -- 判断表单是否是enctype="multipart/form-data",如果是返回true,如果不是返回false
* java.util.List parseRequest(javax.servlet.http.HttpServletRequest request) -- 返回List集合。泛型是FIleItem(文件项)
* void setFileSizeMax(long fileSizeMax) -- 设置上传的文件(单个文件)的大小
* void setSizeMax(long sizeMax) -- 设置上传文件(所有的文件)的总大小
* void setHeaderEncoding(java.lang.String encoding) -- 设置上传文件的名称的编码
* setProgressListener(ProgressListener pListener) -- 上传的时候都有进度条。
**FileItem类**
1.文件项:封装就的表单的部分。
2.方法
* boolean isFormField() -- 判断当前的FileItem对象是普通表单项还是文件上传项
* java.lang.String getFieldName() -- 返回表单中name的名称(name="filedesc")就是filedes
* java.lang.String getString() -- 获取表单中普通项的值
* java.lang.String getString(String encoding) -- 获取表单中普通项的值(使用编码 UTF-8)
* java.lang.String getName() -- 获取文件的名称
* java.io.InputStream getInputStream() -- 获取文件的输入流
* void delete() -- 删除临时文件(在流关闭后执行)
**重要方法**
* isMultipartContent() -- 表单的enctyp是否正确
* setHeaderEncoding() -- 上传文件的中文名称乱码的问题
* isFormField() -- 判断是否普通或者上传项
* getFieldName() -- 获取是普通项name的名称(filedesc)
* getString(String encoding) -- 获取是普通项name属性的值
* getName() -- 获取上传文件项的文件名称
* getInputStream() -- 获取文件的输入流
**多文件上传(js控制)**
* 需要js知识。
**文件的扩展**
1.文件存放的问题
* 上传的文件保存的路径的问题。存放在WebRoot目录下的文件,直接被访问。
* 存放图片(静态资源)
* 存放在WEB-INF目录下不能被直接访问。
* 视频的网站
2.文件名重名的问题
* 产生覆盖的效果。
* 上传的文件时候,把文件的名称转成唯一的文件名。(UUID)
3.如果上传文件的文件夹都是一个,一个文件夹下的文件过多。
* 在一个文件夹下的文件过多的问题。
* 给一个用户一个文件夹。
* 规定文件夹中的文件的总数量。
* 规定多长时间换文件夹。
* 根据算法目录分离。
* 文件已经产生的唯一的文件名。int code = filename.hashCode();
代码:
int code = filename.hashCode();
// 和0xf进行&操作
int dir1 = code & 0xf;
// 把code右移4位
int dir2 = (code >>> 4) & 0xf;
return "/"+dir1+"/"+dir2;
**文件的下载**
1.传统文件下载哪种方式
* 超链接下载
* 如果浏览器可以解析的文件,默认打开了。
* 如果浏览器不能解析文件,弹出下载的窗口。
* 后台的程序下载
* 从服务器向客户端进行下载。(找response对象)
* 两个头一个流
* 两个头:需要设置两个响应的头信息
* Content-Type : text/html;charset=UTF-8
* Content-Dispotition : attachment;filename= 文件的名称 以附件的形式打开文件
* 一个流
* 需要下载的文件的输入流
* 再response输出流,把文件输出到浏览器端。
**文件下载的扩展(队列,树形结构遍历)**
1.在磁盘上指定一个目录,作为根目录,目录包含一些文件,获取目录下所有的文件,显示到页面上,并且提供下载。
2.需求:遍历根目录下的所有的文件进行下载。
**中文文件的下载的问题**
1.先判断浏览器,决定使用什么编码,来把filename编了。
2.怎么判断是用的什么浏览器?
* 获取请求头的信息(User-agent)
* 使用request获取头信息,进行判断。
**文件上传(数据保存到数据库中)**