目录
    1、把上传的文件放到WEB-INF目录下
    2、文件名称(完整路径、文件名称)
    3、中文乱码问题
    4、上传文件同名问题(文件重命名)
    5、一个目录不能存放过多的文件(存放目录打散)
    6、上传的单个文件的大小限制和整个表单大小限制
    7、缓存大小与临时目录
======================================================
1、把上传的文件放到WEB-INF目录下
    如果没有把用户上传的文件存放到WEB-INF目录下,那么用户就可以通过浏览器直接访问上传的文件,这是非常危险的。
    假如说用户上传了一个a.jsp文件,然后用户在通过浏览器去访问这个a.jsp文件,那么就会执行a.jsp中的内容,
    如果在a.jsp中有如下语句:Runtime.getRuntime().exec("shutdown –s –t 1");,那么你就会…
    通常我们会在WEB-INF目录下创建一个uploads目录来存放上传的文件,而在Servlet中找到这个目录需要
    使用ServletContext的getRealPath(String)方法,例如在我的upload1项目中有如下语句:
        ServletContext servletContext = this.getServletContext();
        String savepath = servletContext.getRealPath("/WEB-INF/uploads");
        其中savepath为:"F:\tomcat6_1\webapps\upload1\WEB-INF\uploads"

2、文件名称(完整路径、文件名称)
    上传文件名称可能是完整路径:
    有些浏览器获取的上传文件名称是完整路径,大部分浏览器获取的上传文件名称只是文件名称而已。
    浏览器差异的问题我们还是需要处理一下的。处理这一问题也很简单,无论是否为完整路径,我们都去截取最后一个"\\"后面的内容就可以了。
    String name = file1FileItem.getName();
    int lastIndex = name.lastIndexOf("\\");//获取最后一个"\"的位置
    if(lastIndex != -1) {//注意,如果不是完整路径,那么就不会有"\"的存在。
        name = name.substring(lastIndex + 1);//获取文件名称
    }
    response.getWriter().print(name);

3、中文乱码问题
    当上传的谁的名称中包含中文时,需要设置编码,commons-fileupload组件为我们提供了两种设置编码的方式:
        * request.setCharacterEncoding(String):这种方式是我们最为熟悉的方式了;
        * fileUpload.setHeaderEncdoing(String):这种方式是commons-fileupload组件中的,优先级高与前一种。
    上传文件的文件内容包含中文:
    通常我们不需关心上传文件的内容,因为我们会把上传文件保存到硬盘上!也就是说,文件原来是什么样子,到服务器这边还是什么样子!
    但是如果你有这样的需求,非要在控制台显示上传的文件内容,那么你可以使用fileItem.getString("utf-8")来处理编码。
    文本文件内容和普通表单项内容使用FileItem类的getString("utf-8")来处理编码。

4、上传文件同名问题(文件重命名)
    通常我们会把用户上传的文件保存到uploads目录下,但如果用户上传了同名文件呢?这会出现覆盖的现象。
    处理这一问题的手段是使用UUID生成唯一名称,然后再使用"_"连接文件上传的原始名称。
    例如,用户上传的文件是"我的一寸照片.jpg",在通过处理后,文件名称为:"891b3881395f4175b969256a3f7b6e10_我的一寸照片.jpg",
    这种手段不会使文件丢失扩展名,并且因为UUID的唯一性,上传的文件同名,但在服务器端是不会出现同名问题的。

5、一个目录不能存放过多的文件(存放目录打散)
        一个目录下不应该存放过多的文件,一般一个目录存放1000个文件就是上限了,如果在多,那么打开目录时就会很"卡"。
    你可以尝试打印C:\WINDOWS\system32目录,你会感觉到的。也就是说,我们需要把上传的文件放到不同的目录中。
    但是也不能为每个上传的文件一个目录,这种方式会导致目录过多。所以我们应该采用某种算法来"打散"!打散的方法有很多,
    例如,使用日期来打散,每天生成一个目录。也可以使用文件名的首字母来生成目录,相同首字母的文件放到同一目录下。
    日期打散算法:如果某一天上传的文件过多,那么也会出现一个目录文件过多的情况;
    首字母打散算法:如果文件名是中文的,因为中文过多,所以会导致目录过多的现象。
    我们这里使用hash算法来打散:
        1.获取文件名称的hashCode:int hCode = name.hashCode();
        2.将hCode转换成16进制字符;
        3.使用这个16进制的字符的前两个字符生成目录链。
    int hCode = name.hashCode();//获取文件名的hashCode
    String dir = Integer.toHexString(hCode);
    //与文件保存目录连接成完整路径
    savepath = savepath + "/" + dir.charAt(0) + "/" + dir.charAt(1);
    //因为这个路径可能不存在,所以创建成File对象,再创建目录链,确保目录在保存文件之前已经存在
    new File(savepath).mkdirs();

6、上传的单个文件的大小限制和整个表单大小限制
    限制上传文件的大小很简单,ServletFileUpload类的setFileSizeMax(long)就可以了。参数就是上传文件的上限字节数,
    例如servletFileUpload.setFileSizeMax(1024*10)表示上限为10KB。一旦上传的文件超出了上限,
    那么就会抛出FileUploadBase.FileSizeLimitExceededException异常。我们可以在Servlet中获取这个异常,
    然后向页面输出"上传的文件超出限制"。
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws Exception {
        request.setCharacterEncoding("utf-8");
        DiskFileItemFactory dfif = new DiskFileItemFactory();
        ServletFileUpload fileUpload = new ServletFileUpload(dfif);
        fileUpload.setFileSizeMax(1024 * 10);  // 设置上传的单个文件的上限为10KB
        fileUpload.setSizeMax(1024 * 200);  //设置整个请求的上限为200KB
        try {
            List<FileItem> list = fileUpload.parseRequest(request);
            ......
            fileItem.write(file);
        } catch (Exception e) {
            // 判断抛出的异常的类型是否为FileUploadBase.FileSizeLimitExceededException
            // 如果是,说明上传文件时超出了限制。
            if(e instanceof FileUploadBase.FileSizeLimitExceededException) {
                request.setAttribute("msg", "上传失败!上传的文件超出了10KB!");
                request.getRequestDispatcher("/index.jsp").forward(request, response);
                return;
            }
            if(e instanceof FileUploadBase.SizeLimitExceededException) {
                request.setAttribute("msg", "上传失败!整个表单上传的文件超出了200KB!");
                request.getRequestDispatcher("/index.jsp").forward(request, response);
                return;
            }
            throw new ServletException(e);
        }
    }

7、缓存大小与临时目录
    如果上传一个蓝光电影,先把电影保存到内存中,然后再通过内存copy到服务器硬盘上,那么你的内存能吃的消么?
    所以fileupload组件不可能把文件都保存在内存中,fileupload会判断文件大小是否超出10KB,
    如果超出,是那么就把文件保存到硬盘上;如果没有超出,那么就保存在内存中。
  10KB是fileupload默认的值,我们可以来设置它。
  当文件保存到硬盘时,fileupload是把文件保存到系统临时目录,当然你也可以去设置临时目录。
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws Exception {
        DiskFileItemFactory dfif = new DiskFileItemFactory(1024*20, new File("F:\\temp")); //设置缓存大小20KB 及目录
            ......
    }
10-06 21:03