JavaWeb_文件上传下载_演示fileupload

来源:互联网 发布:百度地图纠偏算法 编辑:程序博客网 时间:2024/05/22 10:44

说明位于src类下面

Apache开源组织提供的处理文件上传的组件:commons-fileupload-1.2.1.jarcommons-io-1.4.jar简单步骤,处理上传文件数据第1步,首先new 一个未经过配置的工厂实例DiskFileItemFactory第2步,用提供的工厂创建一个解析上传文件的解析器实例ServletFileUpload!!第3步,用解析器的parseRequest方法,解析request中提交的数据每个表单项都封装成一个FileItem对象,加入list集合!第4步,迭代list集合第5步,isFormField判断普通字段还是上传字段如果是上传字段getInputStream,一顿狂写下面是十大上传文件的细节1.上传文件的中文乱码1.1 解决上传文件的文件名的中文乱码ServletFileUpload.setHeaderEncoding("UTF-8")1.2 解决普通输入项的值的中文乱码(注意,表单类型为multipart/form-data的时候,设置request的编码是无效的)FileItem.setString("UTF-8");  //解决乱码2.在处理表单之前,要记得调用:ServletFileUpload.isMultipartContent 静态方法判断提交表单的类型,如果该方法返回true,则按上传方式处理,否则按照传统方式处理表单即可。request.getParameter("username")...3.设置解析器缓冲区的大小,以及临时文件的删除设置解析器缓冲区的大小  DiskFileItemFactory.setSizeThreshold(1024*1024);超过临界大小,需设置临时目录:DiskFileItemFactory.setRepository(new File(this.getServletContext().getRealPath("/temp")));临时文件的删除:在程序中处理完上传文件后,一定要记得调用item.delete()方法,以删除临时文件,必须是在关闭流之后,finally代码块中,确保删除成功!4.在做上传系统时,千万要注意上传文件的保存目录,这个上传文件的保存目录绝对不能让外界直接访问到。放到WEB-INF中保护起来!避免别人上传jsp脚本直接运行5.限制上传文件的类型在处理上传文件时,判断上传文件的后缀名是不是允许的6.限制上传文件的大小调用解析器的ServletFileUpload.setFileSizeMax(1024*1024*5);就可以限制上传文件的大小,如果上传文件超出限制,则解析器会抛FileUploadBase.FileSizeLimitExceededException异常,程序员通过是否抓到这个异常,进而就可以给用户友好提示。7.如何判断空的上传输入项String filename = item.getName().substring(item.getName().lastIndexOf("\\")+1);  //""if(filename==null || filename.trim().equals("")){continue;}8、为避免上传文件的覆盖,程序在保存上传文件时,要为每一个文件生成一个唯一的文件名public String generateFileName(String filename){//83434-83u483-934934return UUID.randomUUID().toString() + "_" + filename;}9、为避免在一个文件夹下面保存超过1000个文件,影响文件访问性能,程序应该把上传文件打散后存储。public String generateSavePath(String path,String filename){int hashcode = filename.hashCode();  //121221int dir1 = hashcode&15;int dir2 = (hashcode>>4)&0xf;String savepath = path + File.separator + dir1 + File.separator + dir2;File file = new File(savepath);if(!file.exists()){file.mkdirs();}return savepath;}10、监听上传进度ServletFileUpload upload = new ServletFileUpload(factory);upload.setProgressListener(new ProgressListener(){public void update(long pBytesRead, long pContentLength, int pItems) {System.out.println("当前已解析:" + pBytesRead);}});高级版本//细节:上传进度,前台用AJAX,后台注册一个监听器ProgressListener lisen=new ProgressListener(){//实现每1M更新一次,算法经典~private long flag=-1;public void update(long bytesRead, long contentLength, int items) {//contentLength表示所有文件总大小long full=bytesRead/(1000*1000);if (flag==full) {//开始时尚不足1M时,full=0,flag=-1,不作任何处理return;}//当full每满1M时,将flag=full,便于下1M的时候判断flag=full;System.out.println("正在处理第"+items+"个文件");//items从1开始算起~if (contentLength==-1) {System.out.println("总共上传了:"+bytesRead+"字节");} else {System.out.println("已上传了:"+bytesRead+"of"+contentLength+"字节");}}};//别忘记给upload设置一个监听器upload.setProgressListener(lisen);11、在web页面中添加动态上传输入项12、下载时解决中文乱码//下载之前,要先设置response的头字段,//通知浏览器,以下载文件的方式打开,//注意,解决文件名的中文乱码(用URLEncoder指定utf-8编码)//注意,不能倒着取,因为有可能文件名中也有下划线XX-XX-XX_a_1.txt//得到文件的原始文件名simpleName如 a_1.txtString simpleName=full_name.substring(full_name.indexOf("_")+1);//重点!通知浏览器以下载方式打开下面发送的数据response.setHeader("content-disposition","attachment;filename="+URLEncoder.encode(simpleName, "utf-8"));

UploadServlet1位于web.controller包

package cn.itcast.web.controller;import java.io.IOException;import java.io.InputStream;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class UploadServlet extends HttpServlet {   public void doGet(HttpServletRequest request, HttpServletResponse response)         throws ServletException, IOException {      /*如果表单的enctype属性值为multipart/form-data的话,      在servlet中注意就不能采用getParameter传统方式获取数据      那样,只会返回null      String username=request.getParameter("username");      System.out.println(username);null*/      InputStream in=request.getInputStream();      byte[] buf=new byte[1024];      int len=0;      while((len=in.read(buf))!=-1){         System.out.println(new String(buf,0,len));      }      in.close();      /*下面是表单的enctype属性值为multipart/form-data的时候Post体的值      -----------------------------7de1f327061c      Content-Disposition: form-data; name="username"      sg      -----------------------------7de1f327061c      Content-Disposition: form-data; name="file_1"; filename="a.txt"      Content-Type: text/plain      aaaaa      -----------------------------7de1f327061c      Content-Disposition: form-data; name="file_2"; filename="b.txt"      Content-Type: text/plain      bbbbb      -----------------------------7de1f327061c--*/   }   public void doPost(HttpServletRequest request, HttpServletResponse response)         throws ServletException, IOException {      doGet(request, response);   }}/*MIME协议:POST /day18/servlet/UploadServlet HTTP/1.1Accept: Referer: http://localhost:8080/day18/upload.jspAccept-Language: zh-cnUser-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727)Content-Type: multipart/form-data; boundary=---------------------------7de1282d74043aAccept-Encoding: gzip, deflateHost: localhost:8080Content-Length: 440Connection: Keep-AliveCache-Control: no-cacheCookie: JSESSIONID=F05C1BDA9A447043CFB175DD4A5E8916-----------------------------7de1282d74043aContent-Disposition: form-data; name="username"sg-----------------------------7de1282d74043aContent-Disposition: form-data; name="file_1"; filename="a.txt"Content-Type: text/plainaaaa-----------------------------7de1282d74043aContent-Disposition: form-data; name="file_2"; filename="b.txt"Content-Type: text/plainbbbbb-----------------------------7de1282d74043a--*/



UploadServlet2位于web.controller

package cn.itcast.web.controller;import java.io.File;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;public class UploadServlet2 extends HttpServlet {   public void doGet(HttpServletRequest request, HttpServletResponse response)         throws ServletException, IOException {      //下面是简单地处理上传文件过程~      /*简单步骤,处理上传文件数据      第1步,首先new 一个未经过配置的工厂实例DiskFileItemFactory      第2步,用提供的工厂创建一个解析上传文件的解析器实例ServletFileUpload!!      第3步,用解析器的parseRequest方法,解析request中提交的数据               每个表单项都封装成一个FileItem对象,加入list集合!      第4步,迭代list集合      第5步,isFormField判断普通字段还是上传字段               如果是上传字段getInputStream,一顿狂写*/      //servlet的doPost方法try异常模板代码[try_post]      try {         //第1步,首先new 一个未经配置的工厂实例!         DiskFileItemFactory factory =new DiskFileItemFactory();         //第2步,用提供的工厂作参数,创建一个解析上传文件的解析器实例!         ServletFileUpload upload=new ServletFileUpload(factory);         //第3步,用解析器的parseRequest方法,解析request里的数据         //内部会将每个表单项都封装成一个FileItem对象,加入list集合!         List<FileItem> list=upload.parseRequest(request);         int i=0;         for (FileItem item : list) {            //先判断是否为简单的表单字段            if (item.isFormField()) {               //true表是 a simple form field               String fieldName=item.getFieldName();               //注意getString是针对普通字段,取其值的               String fieldValue=item.getString();               System.out.println("字段名:"+fieldName);               System.out.println("username:"+fieldValue);            } else {               //false代表是 an uploaded file               //代表当前处理的item里面封装的是上传文件               File dest=new File("C:\\upload\\");               //健壮性判断               if (!dest.exists()) {                  dest.mkdirs();               }               //注意getName是针对上传文件,取其文件名的               // item.getName() 如果是IE6     C:\Documents and Settings\Admin\桌面\a.txt                // item.getName() 如果是IE7     a.txt               //所以要截取出来真正的上传文件名               String fileName=item.getName();               fileName=fileName.substring(fileName.lastIndexOf("\\")+1);               //字节流必须用字节数组               byte[] buf = new byte[1024];               int len = 0;               //getInputStream获取关联了上传文件内容的流               InputStream in=item.getInputStream();               //关联目的               OutputStream out = new FileOutputStream(new File("C:\\upload\\"+fileName));               //一顿狂写               while ((len = in.read(buf)) != -1) {                  out.write(buf, 0, len);               }               //最后记得关流,实际开发时,放finally 还要try起来               in.close();               out.close();               }            }      } catch (Exception e) {         //出现异常不要紧,记录下来,并给友好提示!         e.printStackTrace();         request.setAttribute("message", "XX失败");         request.getRequestDispatcher("/message.jsp").forward(request,response);      }      //一路无错,就是上传成功      request.setAttribute("message", "上传成功");      request.getRequestDispatcher("/message.jsp").forward(request,response);   }   public void doPost(HttpServletRequest request, HttpServletResponse response)         throws ServletException, IOException {      doGet(request, response);   }}/*String sql="C:\\Documents and Settings\\Administrator\\桌面\\a.txt";System.out.println(sql.substring(sql.lastIndexOf("\\")+1));结果是:a.txtsql="b.txt";System.out.println(sql.substring(sql.lastIndexOf("\\")+1));结果是:b.txt*/

UploadServlet3位于web.controller

package cn.itcast.web.controller;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.util.Arrays;import java.util.List;import java.util.UUID;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.ProgressListener;import org.apache.commons.fileupload.FileUploadBase.FileSizeLimitExceededException;import org.apache.commons.fileupload.disk.DiskFileItemFactory;import org.apache.commons.fileupload.servlet.ServletFileUpload;/*简单步骤,处理上传文件数据      第1步,首先new 一个未经过配置的工厂实例DiskFileItemFactory      第2步,用提供的工厂创建一个解析上传文件的解析器实例ServletFileUpload!!      第3步,用解析器的parseRequest方法,解析request中提交的数据               每个表单项都封装成一个FileItem对象,加入list集合!      第4步,迭代list集合      第5步,isFormField判断普通字段还是上传字段               如果是上传字段getInputStream,一顿狂写*/public class UploadServlet3 extends HttpServlet {   //成员标记仅用于判断上传的文件是不是全为空~   private boolean flag=false;   public void doGet(HttpServletRequest request, HttpServletResponse response)         throws ServletException, IOException {      //下面是详细地处理上传文件过程~注意各类细节问题~      //定义一个List集合记住允许上传的文件后缀      //允许上传的文件后缀名如下:      List<String> types=Arrays.asList("jpg","bmp","gif","png","txt","avi","pdf","mkv","mp3");      try {         //第1步,首先new 一个未经配置的工厂实例!         DiskFileItemFactory factory =new DiskFileItemFactory();         //细节:解析器缓冲区的大小,如小于10K,直接写硬盘         //工厂设置上传文件缓冲区大小的临界值:单位是K,默认是10K         factory.setSizeThreshold(1024*1024);         //单位是字节,现在是1M         //上面设置了上传文件大小 的临界值是1兆,         //当文件大小超过1兆的时候,会先写到临时目录下         //当上传文件过大时,便会用到临时文件夹(应自己确保临时文件的删除)         factory.setRepository(new File(this.getServletContext().getRealPath("/temp")));         //代表当前web应用,给服务器看         //上传完后记得调用FileItem.delete()删除,必须是在关闭流之后,finally代码块中,确保删除成功!         //第2步,用提供的工厂作参数,创建一个解析上传文件的解析器实例!         ServletFileUpload upload=new ServletFileUpload(factory);         //正式解析之前,必须先设置单个文件的大小限制!5M         upload.setFileSizeMax(1024*1024*50);         //ServletFileUpload的静态方法isMultipartContent(request)         //判断request,是否为上传文件的表单(enctype="mutipart/form-data")         if(!ServletFileUpload.isMultipartContent(request)){            //细节:如果表单不是upload file,那么就可以按传统方式处理            //只有普通表单,request.setCharacterEncoding("utf-8")才有效果            request.setCharacterEncoding("utf-8");            String value=request.getParameter("username");            System.out.println(value);            return;         }         //细节:在解析request之前,必须先解决上传文件名的中文乱码问题         upload.setHeaderEncoding("UTF-8");         //细节:上传进度,前台用AJAX,后台注册一个监听器         ProgressListener lisen=new ProgressListener(){            //实现每1M更新一次,算法经典~            private long flag=-1;            public void update(long bytesRead, long contentLength, int items) {               //contentLength表示所有文件总大小               long full=bytesRead/(1000*1000);               if (flag==full) {                  //开始时尚不足1M时,full=0,flag=-1,不作任何处理                  return;               }               //当full每满1M时,将flag=full,便于下1M的时候判断               flag=full;               System.out.println("正在处理第"+items+"个文件");               //items从1开始算起~               if (contentLength==-1) {                  System.out.println("总共上传了:"+bytesRead+"字节");               } else {                  System.out.println("已上传了:"+bytesRead+"of"+contentLength+"字节");               }            }         };         //别忘记给upload设置一个监听器         upload.setProgressListener(lisen);         //第3步,用解析器的parseRequest方法,解析request里的数据         //内部会将每个表单项都封装成一个FileItem对象,加入list集合!         List<FileItem> list=upload.parseRequest(request);         //System.out.println(list.size()); 什么都不填写时 是1         int i=0;         for (FileItem item : list) {            //先判断是否为简单的表单字段            if (item.isFormField()) {               //true表是 a simple form field               String fieldName=item.getFieldName();               //注意getString是针对普通字段,取其值的               //getString指定码表,可解决普通表单字段的值的中文乱码问题               //解决普通表单字段的值的中文乱码问题(如input name="username",value="中国")               //String fieldValue=item.getString("UTF-8");               //上面指定码表的内部实现如下:               //inputValue = new String(inputValue.getBytes("iso8859-1"),"UTF-8");               //或者自己手动解决普通表单字段的值的中文乱码问题               String fieldValue=item.getString();               fieldValue=new String(fieldValue.getBytes("iso8859-1"),"utf-8");               System.out.println("字段名:"+fieldName);               System.out.println("username:"+fieldValue);            } else {               //注意getName是针对上传文件,取其文件名的               // item.getName() 如果是IE6     C:\Documents and Settings\Admin\桌面\a.txt                // item.getName() 如果是IE7     a.txt               //所以要截取出来真正的上传文件名               String fileName=item.getName();                //如果类型为file的input 没有内容,文件名就为空字符串!               //服务器处理的时候需要先判断文件名是否为空字符串!               //否则,流写数据的时候会抛FileNotFoundExcetpion,因为不能向目录写内容               fileName=fileName.substring(fileName.lastIndexOf("\\")+1);               if (fileName==null || "".equals(fileName.trim())) {                  //继续处理下一个上传文件                  continue;               }               //运行到此标志,证明有文件上传了~               flag=true;               //正式处理上传文件之前,先判断文件名和文件大小               //在这儿点号不用转义               //先获取上传的文件的后缀如txt               String ext=fileName.substring(fileName.lastIndexOf(".")+1);               //再判断允许的后缀集合是否包含,如不包含,则跳转到全局消息               if(!types.contains(ext)){                  //如果上传文件的类型不对,存消息,转发,return;                  request.setAttribute("message", "不支持后缀为."+ext+"的文件上传");                  request.getRequestDispatcher("/message.jsp").forward(request,response);                  return;               }               //false代表是 an uploaded file               //代表当前处理的item里面封装的是上传文件               //细节:处理重复文件问题,生成唯一的文件名,并且打散存储               //调用自定义方法:参数是a.txt,返回的全文件名是:X-X-X_a.txt               String full_name=generateFullName(fileName);               //下面是打散文件,分别存放到指定目录下(如/WEB-INF/upload目录)               //参数是全球唯一的full_name,形如X-X-X_a.txt               //在指定目录下,根据完整文件名的低四次,和次低四位生成文件夹               //返回绝对路径(即完整路径,含全文件名)               String parentPath=this.getServletContext().getRealPath("/WEB-INF/upload");               String fullPath=generateChildPath(parentPath,full_name);               InputStream in=null;               OutputStream out=null;               try {                  //字节流必须用字节数组                  byte[] buf = new byte[1024];                  int len = 0;                  //getInputStream获取关联了上传文件内容的流                  in=item.getInputStream();                  //关联目的                  //out = new FileOutputStream(new File("C:\\upload\\"+fileName));                  //文件所在目录,必须保护起来,坚决不能让外界访问                  out = new FileOutputStream(new File(fullPath));                  //一顿狂写                  while ((len = in.read(buf)) != -1) {                     out.write(buf, 0, len);                  }               }finally {                  if (in != null) {                     try {                        in.close();                     } catch (IOException e) {                        throw new RuntimeException("in关闭失败!");                     }                     in = null;                  }                  if (out != null) {                     try {                        out.close();                     } catch (IOException e) {                        throw new RuntimeException("out关闭失败!");                     }                     out = null;                  }                  //删除临时文件:在程序中处理完上传文件后,                  //一定要记得调用item.delete()方法,以删除临时文件                  //必须是在关闭流之后,finally代码块中,确保删除成功!                  item.delete();  //虽然有时会自动删除临时文件               }               }         }      }catch(   FileSizeLimitExceededException e){          //如果上传文件的大小超过限制,存消息,转发,return;         request.setAttribute("message", "不支持5M以上大小的文件上传");         request.getRequestDispatcher("/message.jsp").forward(request,response);         return;      }catch (Exception e) {         //出现异常不要紧,记录下来,并给友好提示!         e.printStackTrace();         request.setAttribute("message", "XX失败");         request.getRequestDispatcher("/message.jsp").forward(request,response);      }      if(   !flag){         request.setAttribute("message", "您没有上传任何文件~");         request.getRequestDispatcher("/message.jsp").forward(request,response);         return;      }      //一路无错,就是上传成功      request.setAttribute("message", "上传成功");      request.getRequestDispatcher("/message.jsp").forward(request,response);   }   //下面是打散文件,分别存放到指定目录下(如/WEB-INF/upload目录)   //参数是全球唯一的full_name,形如X-X-X_a.txt   //在指定目录下,根据完整文件名的低四次,和次低四位生成文件夹   //根据父目录和完整文件名称,返回绝对路径(即完整路径,含全文件名)   private String generateChildPath(String parentPath, String full_name) {      int hashCode=full_name.hashCode();//相同字符,哈希值一样,共4*8=32位      int dir1=hashCode&15;      int dir2=(hashCode>>4)&0xf;      //这样就可以保存16*1000*16个文件,如果不够用,还可以dir3      //因为部署到Linux系统,所以要做到与平台无关File.separator\      File file=new File(parentPath+File.separator+dir1+File.separator+dir2);      //健壮性判断      if (!file.exists()) {         //注意多层目录必须加S         file.mkdirs();      }      return file+File.separator+full_name;   }   //细节:处理重复文件问题,生成唯一的文件名,   //自定义方法1:参数是a.txt,返回的全文件名是:X-X-X_a.txt   //d92569e5-cb97-4305-8cc1-b72a5d91551b_a.txt   private String generateFullName(String fileName) {      return UUID.randomUUID().toString()+"_"+fileName;   }   public void doPost(HttpServletRequest request, HttpServletResponse response)         throws ServletException, IOException {      doGet(request, response);   }}/*String sql="C:\\Documents and Settings\\Administrator\\桌面\\a.txt";System.out.println(sql.substring(sql.lastIndexOf("\\")+1));结果是:a.txtsql="b.txt";System.out.println(sql.substring(sql.lastIndexOf("\\")+1));结果是:b.txt*/



ListFilesServlet位于web.controller
package cn.itcast.web.controller;import java.io.File;import java.io.IOException;import java.util.LinkedHashMap;import java.util.Map;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;//列出网站所有可供下载的文件//关系是如何保存迭代出来的文件名public class ListFilesServlet extends HttpServlet {   public void doGet(HttpServletRequest request, HttpServletResponse response)         throws ServletException, IOException {      String parentPath=this.getServletContext().getRealPath("/WEB-INF/upload");      //迭代出upload目录下的所有文件,      //保存到map集合,key是全球唯一的full_name,形如X-X-X_a.txt      //value是singleName,形如a.txt      Map<String, String> map=new LinkedHashMap<String, String>();      //调用递归方法,迭代出目录下的所有文件      File dir=new File(parentPath);      listAllFiles_1(dir,map);      System.out.println(map);//{}      //健壮性判断      if (map.size()==0) {         request.setAttribute("message", "暂无文件可供下载");         request.getRequestDispatcher("/message.jsp").forward(request, response);         return;      }      //全部存到map之后,存到request带给jsp显示      request.setAttribute("map", map);      request.getRequestDispatcher("/WEB-INF/jsp/listfiles.jsp").forward(request, response);   }   private void listAllFiles_2(File file, Map<String, String> map) {      //老方的递归,先判断file是文件还是文件夹      //如果是文件夹,取出所有文件,继续递归~      //如果是文件,添加到map      if (!file.isFile()) {         File[] files=file.listFiles();         for (File f : files) {            listAllFiles_2(f,map);         }      } else {         //file.getName() 就是XX-XX-XX_a.txt         //value就是a.txt         //8347824284-343-343_a_b.txt         map.put(file.getName(), file.getName().substring(file.getName().indexOf("_")+1));          //<a href="/servlet?filename=文件在服务器的UUID名称">文件的原始文件名(A.TXT)</a>      }   }   private void listAllFiles_1(File dir, Map<String, String> map) {      //老毕的递归,直接列出dir下所有文件迭代,      //再判断是文件还是文件夹      //如果是文件夹,继续递归~      //如果是文件,添加到map      File[] files=dir.listFiles();      for (File f : files) {         if (!f.isFile()) {            listAllFiles_1(f,map);         } else {            map.put(f.getName(), f.getName().substring(f.getName().indexOf("_")+1));         }      }   }   public void doPost(HttpServletRequest request, HttpServletResponse response)         throws ServletException, IOException {      doGet(request, response);   }}


DownLoadServlet位于web.controller

package cn.itcast.web.controller;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.URLEncoder;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class DownLoadServlet extends HttpServlet {   public void doGet(HttpServletRequest request, HttpServletResponse response)         throws ServletException, IOException {      //接收listfiles页面中发来的请求(注意get方式,中文乱码要手动解决)      //request.setCharacterEncoding("utf-8");仅针对post提交有效      //得到要下载的文件名  uuid文件名      String full_name=request.getParameter("full_name");      //URL后参数形式提交过来的中文,只能手工转~      full_name=new String(full_name.getBytes("iso8859-1"),"utf-8");      //调用方法,反向根据full_name得出文件在upload父目录下的哪个子目录      //父目录例如/WEB-INF/upload目录      //参数是全球唯一的full_name,形如X-X-X_a.txt      //在指定目录下,根据完整文件名的低四次,和次低四位找到文件夹      //返回绝对路径(即完整路径,含全文件名)      String parentPath=this.getServletContext().getRealPath("/WEB-INF/upload");      String fullPath=generateChildPath(parentPath,full_name);      File file=new File(fullPath);      //得到fullPath,先别急着提供下载,先进行健壮性判断      if (!file.exists()) {         //如果文件不存在,存消息,跳,返回         request.setAttribute("message", "您来晚了,资源已被销毁");         request.getRequestDispatcher("/message.jsp").forward(request,response);         return;      }      //一路OK,这时才提供下载      //下载之前,要先设置response的头字段,      //通知浏览器,以下载文件的方式打开,      //注意,解决文件名的中文乱码(用URLEncoder指定utf-8编码)      //注意,不能倒着取,因为有可能文件名中也有下划线XX-XX-XX_a_1.txt      //得到文件的原始文件名simpleName如 a_1.txt      String simpleName=full_name.substring(full_name.indexOf("_")+1);      //重点!通知浏览器以下载方式打开下面发送的数据      response.setHeader("content-disposition","attachment;filename="+URLEncoder.encode(simpleName, "utf-8"));      InputStream in = null;      OutputStream out = null;      try {         byte[] buf = new byte[1024];         int len = 0;         in=new FileInputStream(file);         out=response.getOutputStream();         while ((len = in.read(buf)) != -1) {            out.write(buf, 0, len);         }      } catch (IOException e) {         e.printStackTrace();      } finally {         if (in != null) {            try {               in.close();            } catch (IOException e) {               throw new RuntimeException("in关闭失败!");            }            in = null;         }         if (out != null) {            try {               out.close();            } catch (IOException e) {               throw new RuntimeException("out可以不用管,浏览器销毁response时,自动关流!");            }            out = null;         }      }   }   private String generateChildPath(String parentPath, String full_name) {      //调用方法,反向根据full_name得出文件在upload父目录下的哪个子目录      //父目录例如/WEB-INF/upload目录      //参数是全球唯一的full_name,形如X-X-X_a.txt      //在指定目录下,根据完整文件名的低四次,和次低四位找到文件夹      //返回绝对路径(即完整路径,含全文件名)      int hashCode=full_name.hashCode();      int dir1=hashCode&15;      int dir2=(hashCode>>4)&0xf;      return parentPath+File.separator+dir1+File.separator+dir2+File.separator+full_name;   }   public void doPost(HttpServletRequest request, HttpServletResponse response)         throws ServletException, IOException {      doGet(request, response);   }}



UploadServlet3_Copy位于web.controller

package cn.itcast.web.controller;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.util.Arrays;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.FileUploadBase.FileSizeLimitExceededException;import org.apache.commons.fileupload.disk.DiskFileItemFactory;import org.apache.commons.fileupload.servlet.ServletFileUpload;/*简单步骤,处理上传文件数据      第1步,首先new 一个未经过配置的工厂实例DiskFileItemFactory      第2步,用提供的工厂创建一个解析上传文件的解析器实例ServletFileUpload!!      第3步,用解析器的parseRequest方法,解析request中提交的数据               每个表单项都封装成一个FileItem对象,加入list集合!      第4步,迭代list集合      第5步,isFormField判断普通字段还是上传字段               如果是上传字段getInputStream,一顿狂写*/public class CopyOfUploadServlet3 extends HttpServlet {   public void doGet(HttpServletRequest request, HttpServletResponse response)         throws ServletException, IOException {      //下面是详细地处理上传文件过程~注意各类细节问题~      //允许上传的文件后缀名如下:      List<String> types=Arrays.asList("jpg","bmp","gif","png","txt","avi","pdf");      try {         //第1步,首先new 一个未经配置的工厂实例!         DiskFileItemFactory factory =new DiskFileItemFactory();         //细节:解析器缓冲区的大小         factory.setSizeThreshold(1024*1024);//单位是字节,现在是1M         //当上传文件过大时,便会用到临时文件夹(应自己确保临时文件的删除)         factory.setRepository(new File(this.getServletContext().getRealPath("/temp")));         //第2步,用提供的工厂作参数,创建一个解析上传文件的解析器实例!         ServletFileUpload upload=new ServletFileUpload(factory);         //正式解析之前,必须先设置单个文件的大小限制!5M         upload.setFileSizeMax(1024*1024*5);         if(!ServletFileUpload.isMultipartContent(request)){            //细节:如果表单不是upload file,那么就可以按传统方式处理            //只有普通表单,request.setCharacterEncoding("utf-8")才有效果            request.setCharacterEncoding("utf-8");            String value=request.getParameter("username");            System.out.println(value);            return;         }         //细节:在解析request之前,必须先解决上传文件名的中文乱码问题         upload.setHeaderEncoding("UTF-8");         //第3步,用解析器的parseRequest方法,解析request里的数据         //内部会将每个表单项都封装成一个FileItem对象,加入list集合!         List<FileItem> list=upload.parseRequest(request);         int i=0;         for (FileItem item : list) {            //先判断是否为简单的表单字段            if (item.isFormField()) {               //true表是 a simple form field               String fieldName=item.getFieldName();               //注意getString是针对普通字段,取其值的               //getString指定码表,可解决普通表单字段的值的中文乱码问题               //String fieldValue=item.getString("UTF-8");               //或者自己手动解决普通表单字段的值的中文乱码问题               String fieldValue=item.getString();               fieldValue=new String(fieldValue.getBytes("iso8859-1"),"utf-8");               System.out.println("字段名:"+fieldName);               System.out.println("username:"+fieldValue);            } else {               //注意getName是针对上传文件,取其文件名的               // item.getName() 如果是IE6     C:\Documents and Settings\Admin\桌面\a.txt                // item.getName() 如果是IE7     a.txt               //所以要截取出来真正的上传文件名               String fileName=item.getName();               fileName=fileName.substring(fileName.lastIndexOf("\\")+1);               if (fileName==null || "".equals(fileName.trim())) {                  continue;               }               //正式处理上传文件之前,先判断文件名和文件大小               //在这儿点号不用转义               String ext=fileName.substring(fileName.lastIndexOf(".")+1);               if(!types.contains(ext)){                  //如果上传文件的类型不对,存消息,转发,return;                  request.setAttribute("message", "不支持后缀为."+ext+"的文件上传");                  request.getRequestDispatcher("/message.jsp").forward(request,response);                  return;               }               //false代表是 an uploaded file               //代表当前处理的item里面封装的是上传文件               /*File dest=new File("C:\\upload\\");               //健壮性判断               if (!dest.exists()) {                  dest.mkdirs();               }*/               InputStream in=null;               OutputStream out=null;               try {                  //字节流必须用字节数组                  byte[] buf = new byte[1024];                  int len = 0;                  //getInputStream获取关联了上传文件内容的流                  in=item.getInputStream();                  //关联目的                  //out = new FileOutputStream(new File("C:\\upload\\"+fileName));                  //文件所在目录,必须保护起来,坚决不能让外界访问                  out = new FileOutputStream(new File(this.getServletContext().getRealPath("/WEB-INF/upload")+"\\"+fileName));                  //一顿狂写                  while ((len = in.read(buf)) != -1) {                     out.write(buf, 0, len);                  }               }finally {                  if (in != null) {                     try {                        in.close();                     } catch (IOException e) {                        throw new RuntimeException("in关闭失败!");                     }                     in = null;                  }                  if (out != null) {                     try {                        out.close();                     } catch (IOException e) {                        throw new RuntimeException("out关闭失败!");                     }                     out = null;                  }                  //删除临时文件:在程序中处理完上传文件后,                  //一定要记得调用item.delete()方法,以删除临时文件                  //必须是在关闭流之后,finally代码块中,确保删除成功!                  item.delete();                 }               }         }      }catch(   FileSizeLimitExceededException e){          //如果上传文件的大小超过限制,存消息,转发,return;         request.setAttribute("message", "不支持5M以上大小的文件上传");         request.getRequestDispatcher("/message.jsp").forward(request,response);         return;      }catch (Exception e) {         //出现异常不要紧,记录下来,并给友好提示!         e.printStackTrace();         request.setAttribute("message", "XX失败");         request.getRequestDispatcher("/message.jsp").forward(request,response);      }      //一路无错,就是上传成功      request.setAttribute("message", "上传成功");      request.getRequestDispatcher("/message.jsp").forward(request,response);   }   public void doPost(HttpServletRequest request, HttpServletResponse response)         throws ServletException, IOException {      doGet(request, response);   }}/*String sql="C:\\Documents and Settings\\Administrator\\桌面\\a.txt";System.out.println(sql.substring(sql.lastIndexOf("\\")+1));结果是:a.txtsql="b.txt";System.out.println(sql.substring(sql.lastIndexOf("\\")+1));结果是:b.txt*/



substringtest位于junit.test包

package junit.test;public class substringtest {public static void main(String[] args){String sql="C:\\Documents and Settings\\Administrator\\桌面\\a.txt";System.out.println(sql.substring(sql.lastIndexOf("\\")+1));//a.txtsql="b.txt";System.out.println(sql.substring(sql.lastIndexOf("\\")+1));//b.txt}}



toLowerCase位于junit.test包

package junit.test;import java.io.File;import org.junit.Test;public class toLowerCase {@Testpublic void test(){System.out.println("09809098098jpgAD.JPG".toLowerCase());//09809098098jpgad.jpg}@Testpublic void test2(){System.out.println(File.pathSeparator);//;System.out.println(File.separator);//\}}



index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>        <title>My JSP 'index.jsp' starting page</title>  </head>    <body>    <a href="/day18/upload.jsp">上传文件</a>    <a href="/day18/upload2.jsp">动态上传文件</a>    <a href="/day18/servlet/ListFilesServlet">列出所有上传文件</a>     <form action="${pageContext.request.contextPath }/servlet/UploadServlet3" method="post" >     上传用户:<input type="text" name="username"><br/>     <input type="submit" value="普通表单" />     </form>  </body></html>
upload.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <title>上传页面</title>  </head>  <body>     <form action="${pageContext.request.contextPath }/servlet/UploadServlet3" method="post" enctype="multipart/form-data">     上传用户:<input type="text" name="username"><br/>       上传文件1:<input type="file" name="file_1"><br/>       上传文件2:<input type="file" name="file_2"><br/>     <input type="submit" value="开始上传" />     </form>  </body></html>


upload2.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <title>动态添加file</title>    <script type="text/javascript">       function addFile(){          var div=document.getElementById("div_id");          //alert(div);          //创建input type为file          var file=document.createElement("input");          file.type="file";          //千万要有名字~          file.name="XXX";          //创建input type为button          var btn=document.createElement("input");          btn.type="button";          btn.value="删除";          btn.onclick=function del(){             //父是小div,小div的父把小div删除掉~             this.parentNode.parentNode.removeChild(this.parentNode);          }          //创建个小的div          var small_div=document.createElement("div");          //黄鹰抓住了鹞子的脚,两个都扣了环          small_div.appendChild(file);          small_div.appendChild(btn);          div.appendChild(small_div);       }    </script>  </head>  <body>     <form action="${pageContext.request.contextPath }/servlet/UploadServlet3"method="post" enctype="multipart/form-data" >     <table border="1px">           <tr>              <td>用户名:</td>              <td><input type="text" name="username"></td>           </tr>           <tr>              <td><input type="button" value="添加上传" onclick="addFile()"></td>              <td>                 <div id="div_id"></div>              </td>           </tr>           <tr>                 <td><input type="submit" value="开始上传"/></td>           </tr>     </table>     </form>  </body></html>


listfiles.jsp


<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>        <title>显示所有文件列表</title>  </head>    <body>        注意两点:中文作为url地址后参数时,需要编码        url结合param可以作到这一点!同时会自动添加web应用名<br/>        下载文件有:<br/>        <c:forEach var="entry" items="${requestScope.map}">           <c:url var="url" value="/servlet/DownLoadServlet" scope="request">              <c:param name="full_name" value="${entry.key}"></c:param>           </c:url>           ${entry.value }           <a href="${url }">下载</a><br/>        </c:forEach>  </body></html>




0 0
原创粉丝点击