web中解决文件上传

来源:互联网 发布:thinkpad系列知乎 编辑:程序博客网 时间:2024/06/08 18:59

    一.准备需要上传的磁盘文件

   文件准备就不用说了,先建立一个jsp,此jsp负责用户上传文件。此jsp中有一form表单,此表单有三个特点,或者是说文件上传的三个前提。

   a、表单的method必须是post

    b、表单的enctype属性必须是multipart/form-data

    c、表单中提供<inputtype="file"/>类型的上传输入域

   下面是具体的代码:
[html] view plain copy
  1. <form action="${pageContext.request.contextPath}/servlet/UploadServlet2" method="post" enctype="multipart/form-data">  
  2.         name:<input type="text" name="name"/><br/>  
  3.          file1:<input type="file" name="photo"/><br/>  
  4.         file2:<input type="file" name="photo"/><br/>  
  5.         <input type="submit" value="上传"/>  
  6.     </form>  

   二.开始上传

   我们建立一个servlet,在此servlet中开始准备上传时用到的类,也就是DiskFileItemFactory类,和ServletFileuqLoad类,DiskFileItemFactory负责管理磁盘文件,ServletFileuqLoad类负责上传和解析文件。下面是具体的代码。

[java] view plain copy
  1. <pre name="code" class="java">public void doGet(HttpServletRequest request, HttpServletResponse response)  
  2.             throws ServletException, IOException {  
  3.         request.setCharacterEncoding("UTF-8");// 解决上传的中文文件乱码问题  
  4.         response.setContentType("text/html;charset=UTF-8");  
  5.         // 1.0. 检查是否是multipart/form-data类型的  
  6.         boolean isMultipart = ServletFileUpload.isMultipartContent(request);  
  7.         if (!isMultipart) {  
  8.             throw new RuntimeException(  
  9.                     "The form's enctype attribute value must be multipart/form-data");  
  10.         }  
  11.   
  12.         // 2.0开始实现上传,创建上传文件需要用到的两个对象  
  13.         DiskFileItemFactory factory = new DiskFileItemFactory();// 产生FileItem的工厂  
  14.         ServletFileUpload sfu = new ServletFileUpload(factory); //因为解析器依赖于这个工厂,所以将这个工厂传进去  
  15.   
  16.         // 3.0创建一个容器来接收解析的内容  
  17.         List<FileItem> items = new ArrayList<FileItem>();  
  18.           
  19.         //4.0将上传的文件信息放到容器中  
  20.         try {  
  21.             items = sfu.parseRequest(request);  
  22.         }  catch (FileUploadException e) {  
  23.             e.printStackTrace();  
  24.         }  
  25.   
  26.         //5.0  遍历  开始处理解析的内容,这里封装了两个方法,一个是专门处理FormField的方法,一个是专门处理UploadField的方法  
  27.         for (FileItem item : items) {  
  28.             if (item.isFormField()) {  
  29.                 processFormField(item);// 处理普通p上传字段  
  30.             } else {  
  31.                 processUploadField(item);// 处理上传字段  
  32.             }  
  33.               
  34.         }  
  35.   
  36.     }  
  37.   
  38.   
  39.       public void doPost(HttpServletRequest request, HttpServletResponse response)  
  40.             throws ServletException, IOException {  
  41.         doGet(request, response);  
  42.   
  43.     }  

  下面是两个需要解析的方法,一个是一个是专门处理FormField的方法(也就是表单中普通的字段),一个是专门处理UploadField的方法(也就是需要上传的文件)。

  三、解析上传文件并保存到服务器

   1、专门处理FormField的方法

[java] view plain copy
  1. <pre name="code" class="java">protected void processFormField(FileItem item) {  
  2.         // 打印到控制台  
  3.         String fieldName = item.getFieldName();  
  4.         String value = "";  
  5.         try {  
  6.             value = item.getString("UTF-8");// 解决普通字段的编码问题,得到普通字段的值  
  7.         } catch (UnsupportedEncodingException e) {  
  8.             e.printStackTrace();  
  9.         }  
  10.         System.out.println(fieldName + "=" + value);  
  11.     }  

   2、专门处理FormField的方法(此方法负责存放文件)

[java] view plain copy
  1. <pre name="code" class="java">protected void processUploadField(FileItem item) {  
  2.         try {  
  3.   
  4.             // 找到一个存放位置 存放文件名  
  5.             String fileName = item.getName();// 上传的文件的文件名  
  6.                                                 // C:\Users\wzhting\Desktop\a.txt  
  7.                                                 // a.txt(浏览器不同)  
  8.             if (fileName != null) {  
  9.                 // 控制只能能上传图片  
  10.                 // if (!item.getContentType().startsWith("image")) {  
  11.                 // return;  
  12.                 // }  
  13.                 fileName = FilenameUtils.getName(fileName);  
  14.                 fileName = IdGenertor.genGUID() + "_" + fileName;  
  15.             }  
  16.   
  17.             // 存放路径  
  18.             String realPath = getServletContext().getRealPath("/WEB-INF/files");  
  19.   
  20.             // 生成一个子目录  
  21.             String childDirectory = genChildDirectory(realPath, fileName);  
  22.             File storeDirectory = new File(realPath + File.separator  
  23.                     + childDirectory);  
  24.             //如果目录不存在,就创建一个  
  25.             if (!storeDirectory.exists()) {  
  26.                 storeDirectory.mkdirs();  
  27.             }  
  28.             //开始存放磁盘文件  
  29.             item.write(new File(storeDirectory, fileName));  
  30.         } catch (Exception e) {  
  31.             e.printStackTrace();  
  32.         }  
  33.   
  34.     }  
   3、为了避免上传的文件存在同一个文件夹下(对于后期的遍历查找不利)我们可以写一个方法来临时创建分目录。

[java] view plain copy
  1. <pre name="code" class="java">// 按照hashcode创建分目录 放置一个文件夹下面的上传文件过度  
  2.     private String genChildDirectory(String realPath, String fileName) {  
  3.         int hashCode = fileName.hashCode();  
  4.         int dir1 = hashCode & 0xf;  
  5.         int dir2 = (hashCode & 0xf0) >> 4;  
  6.         String str = dir1 + File.separator + dir2;  
  7.         File file = new File(realPath, str);  
  8.         if (!file.exists()) {  
  9.             file.mkdirs();  
  10.         }  
  11.         return str;  
  12.   
  13.     }  
  14.   
  15.     // 按照时间创建分目录 放置一个文件夹下面的文件过多  
  16.     protected String genChildDirectory(String realPath) {  
  17.         Date now = new Date();  
  18.         DateFormat df = new SimpleDateFormat("yyyy-MM-dd");  
  19.         String str = df.format(now);  
  20.   
  21.         File file = new File(realPath, str);  
  22.         if (!file.exists()) {  
  23.             file.mkdirs();  
  24.         }  
  25.         return str;  
  26.     }  
   上面两个方法一个是根据日期来创建目录,一个是根据hashcode创建目录。

   四、其它上传文件中经常用到的功能

   1.限制上传文件的类型,比如说,限制只能上传照片

[java] view plain copy
  1. if (!item.getContentType().startsWith("image")) {  
  2.     return;  
  3.  }  

   2.限制一下上传文件的大小

[java] view plain copy
  1. DiskFileItemFactory factory = new DiskFileItemFactory();// 产生FileItem的工厂  
  2.         ServletFileUpload sfu = new ServletFileUpload(factory); //因为解析器依赖于这个工厂,所以将这个工厂传进去  
  3.         // 限制上传文件大小  
  4.         sfu.setFileSizeMax(1024 * 196);// 限制单个文件的大小不超过200kb  
  5.         //sfu.setSizeMax(5*1024*1024);//限制上传的总文件大小不超过5M  
  6.         // 3.0创建一个容器来接收解析的内容  
  7.         List<FileItem> items = new ArrayList<FileItem>();  
  8.         //4.0将上传的文件信息放到容器中  
  9.         try {  
  10.             items = sfu.parseRequest(request);  
  11.         } catch (FileUploadBase.FileSizeLimitExceededException e) {  
  12.             response.getWriter().write("照片不能超过196k");  
  13.         } catch (FileUploadException e) {  
  14.             e.printStackTrace();  
  15.         }