//文件上传,和下载
//1,分为两大类。CLOB和BLOB文件,clob是指大文本数据,比如视频,音乐文件等;blob是指二进制文件方式传输(即可以放一切文件)。
处理大型数据:
①存储路径,通过jdbc存储文件路径,然后根据IO操作处理。
②直接将文件存入数据库。CLOB和BLOB文件方式来处理。
//clob实现
//upload.jsp
上面换行错误(纯手写txt,截图,method,写错)
<body>
<form action="$pageContext.request.contextPath/Servlet/UploadServlet " menthod="post" enctpye="multipart/from-data">
文件说明:<input type="file" name="uploadfiletext"><br/>
<input type="file" name="upload"><br/>
<input type="submit" value="上传">
</from>
//动态多文件上传,服务端逻辑是一样的,只需要在客户端,实现多文件上传控件即可
//加入commons-fileupload工具类
//文件上传的服务器,UploadServlet,新建在
$pageContext.request.contextPath/Servlet/UploadServlet路径下
public class UploadServlet extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
//创建文件上传工厂类实例对象
DiskFileItemFactory factory = new DiskFileItemFactory();
//创建文件上传的ServletFileUpload实例对象
ServletFileUpload upload= new ServletFileUpload(factory );
upload.setFileMax(1024*10)
//利用ServletFileUpload实例对象upload解析request里的文件内容
//try{
List<FileItem> items=upload.parseRequest(request);
//读取数组中的数据
for(FileItem fileitem:items){
//1,数据不能为空.上面省略这个判断;2,不为空时,区分普通项和文件项
//通过FileItem.isFromField()方法判断,true为普通项,false为文件项
if(fileitem.isFromField()){
String fileName =fileitem.getFileName();//获取普通想的name属性值
String fileValue =fileitem.getString();//获取文本内容
System.out.println(fileName+":"+fileValue);
}
else{
//文件项,获取上传文件名称getName()
String fileName =fileitem.getName();
//获取上传文件输入流getInputStream()
InputStream in =fileitem.getInputStream();
//此处上传文件是自定义路径,这样是很危险的,例如上传一个包含恶意代码jsp文件,
//因此上传到WEB-INF目录中,在浏览器中不能访问WEB-INF目录中的内容
String realPath=getServletContext().getRealPath("/uploads");
OutputStream out =new FileOutputStream(new File(realPath,fileName));
IOUtils.copy(in,out);//将上传文件进行保存。
in.close();
out.close();
}
}
//}
}
public void doPost(HttpServlet request,HttpServletResponse) throws ServletException,IOException{
doGet(request,response);
}
}
//上传文件同名处理,为每一个上传文件增加一个UUID,UUID类中的randomUUID()可以生成一个唯一标示符
fileName=UUID.randomUUID().toString()+fileName;
//上传文件乱码问题
1,利用request对象的,setCharacterEncoding(“UTF-8”);写在doGet()和doPost()的前面;
2,利用ServletFileUpload,setCharacterEncoding(“UTF-8”);
//一个目录不能存放过多的文件
1,根据上传时间进行分离,2,根据上传用户进行目录分离,3,按固定数量进行分离,4,按照唯一文件名的hashCode进行分离
//上传单个文件的大小限制
1,利用ServletFileUpload类的setFileMax(long);例:ServletFileUpload.setFileMax(1024*10),设置为10kb;
//上传文件总大小的问题
//利用多文件上传时,还需要设置文件的总大小。利用ServletFileUpload类的setSizeMax(long);
//文件缓存大小,和临时目录。一般上传文件都是存储在内存中,然后在拷贝到服务器磁盘中,但是如果文件过大,就需要手动的设置文件缓存大小
//和上传文件临时目录
手动修改上传文件大小及临时目录:
1,DiskFileItemFactory.setSizeThreshold(缓存字节数);默认缓存字节数10kb;
2,DiskFileItemFactory.setRepository(new File(getServletContext().getRealPath(临时目录相对路径)),如果需要删除临时目录下的文件,
调用FileItem的delete()方法即可。
例子:factory.setSizeThreshold(1024*1024);factory.setRepository(newFile(getServletContext().getRealPath(/tmp));
逻辑机制:当文件上传成功后,删除临时目录中的临时文件。
//流的选择,最好选择bufferdInputStream和bufferdOutputStream
//文件上传进度监听,实时看到进度,可以使用ServletFileUpload提供的setProgressListener()方法,在客户端配合ajax技术实现
需要监听:1,(useTime)已用时间=当前时间-开始时间,2,(speed)速度=已传大小/已用时间,
3,(restBytes)剩余大小=总大小-已经上传大小,4,(restTime)剩余时间=剩余大小/速度
//增加监听
//long pBytesRead:此时已经能上传的文件大小,long pContextLength:上传文件的总大小,int pItems: 当前上传文件,是表单里的第几个元素
upload.setProgressListener(new ProgressListener){
public void update(long pBytesRead,long pContextLength,int pItems){
long currentTime = System.currentTimeMills();//当前时间
long useTime = currentTime - startTime;
long speed = pBytesRead /pBytesRead;
long restBytes= pContextLength - pBytesRead;
long restTime = restBytes/speed;
}
}
实例:
//1,index.jsp
//2.fileupload.jsp
<body>
<from action="...../FileUploadServlet" method="post" enctype="mutliport/from-data">
文件说明:〈input type="text" name="fileName"〉</br>
<input type="file" value="upload"> </br>
<input type="submmit" value="上传">
<from>
//服务端
pubic class FileUploadServlet extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response){
request.setCharacterEncoding("UTF-8");
//创建文件上传工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//设置缓存大小
factory.setSizeThreshold(1024*1024);
//得到上传文件目录
String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");
//上传时生成临时文件保存目录
String tempPath = this.getServletContext().getRealPath("/WEN-INF/temp");
File file = new File(tempPath);
if(file.exists()){
//创建临时目录
file.mkdirs();
}
//临时文件目录
//factory.setRepository(new File(getServletContext().getRealPath("/tmp")));
//创建Servlet文件上传实例对象
ServletFileUpload upload = ServletFileUpload(factory);
final long startTime = System.currentTimeMills();
//为上传文件增加进程监听
upload.setProgressListener(new ProgressListener()){
public void uploadProgress(long pBytesRead,long pContextLength,int pItems){
long currentTime = System.currentTimeMills();//当前时间
long useTime = currentTime - startTime;
long speed = pBytesRead /pBytesRead;
long restBytes= pContextLength - pBytesRead;
intrestTime = restBytes/speed;
}
}
try{
//限制上传单个3M和总大小10M
upload.setFileSizeMax(1024*1024*3);
upload.setSizeMax(1024*1024*10);
List<FileItem> iteams =upload.praseRequest(request) ;
if(!(iteams==null)){
for(FileItem fileItem :iteams ){
if(fileItem.isFromFile){
String fileName = fileItem.getFileName();
String fieldValue = fileItem.getString();
System.out.println(fileName+":"+fieldValue);
}else{
String fileName = fileItem.getName();
//解决浏览器过旧问题
int index = fileName.lastIndexOf("\\");
if(index>=0){fileName.substring(index+1);}
//防止文件同名
fileName = UUID.randomUUID().toString+fileName;
InputStream in = fileItem.getInputStream();
//利用hashcode进行目录分离,hasCode根据对象的地址或字符串或者数字算出来的int类型的数值;
int hascode = fileName.hasCode();
//生成一级目录
int d1 = hashcode&0xf;
//生成二级目录
int d2 = (hashcode>>>4)&0xf;
String realPath = getServletContext().getRealPath("/WEB-INF/uploads/"+d1+"/"+d2);
//boolen mkdir()创建此抽象path的目录;mkdirs()创建此抽象路径名指定的目录,包括创建必须但不存在的父目录
//用法:1,file.mkdirs("/a/aa/aaa");file是一个File对象。2,在申明时,就加入File file=new File("/a/aa/aaa");
new File(realPath).mkdirs();
BufferdOutputStream out = new FileBufferdOut(new File(realPath,fileName));
IOUtils.copy(in,out);
in.close();
out.close();
}
}
}catch(Exception e){
//设置传给前台的setError,setSuccess
}
}
}
public void doPost(HttpServletRequest request,HttpServletResponse response){
request.setCharacterEncoding("UTF-8");
doGet(request,response);
}
}