学习笔记之表单文件上传

本文用于记录学习心得和笔记。

上传文件时表单要求

  1. 请求方式post
  2. 设置enctype="multipart/form-data"
  3. 表单中添加文件表单项<input type="file" name="" />

Commons FileUpload处理文件上传

简介:FileUpload解析符合RFC 1867 “基于表单的HTML文件上传”的HTTP请求 。也就是说,如果使用POST方法提交HTTP请求,并且使用内容类型“multipart / form-data”,则FileUpload可以解析该请求,并以调用方容易使用的方式提供结果。

  1. 依赖包:commons-fileupload.jar, commons-io.jar
  2. 相关类:DiskFileItemFactory ,工厂;ServletFileUpload,解析器;FileItem,表单项;
  3. 使用:第一步,创建解析器工厂,
1
DiskFileItemFactory factory = new DiskFileItemFactory();

第二步,得到解析器,

1
ServletFileUpload fileUpload = new ServletFileUpload(factory);

第三步,使用ServletFileUpload的parseRequest方法解析请求,得到表单项的集合,

1
List<FileItem> list = fileUpload.parseRequest(request);

  1. FileItem类的常用方法:
    boolean isFormFiled() —是否是普通表单项
    String getFiledName() —返回表单项名称
    String getString(String encoding) —返回普通表单项的内容,参数是编码,不指定则为默认编码
    String getName() —返回上传的文件的名称
    int getSize() —返回上传文件的大小,单位是字节
    void write(File file) —将文件内容写入到指定的文件中

文件上传的细节

  1. 一般保存在WEB-INF目录下
    目的是不让浏览器直接访问到
  2. 文件名称相关问题
    有的浏览器上传的文件名带有绝对路径,这时要分割字符串
    文件名称重复问题,使用uuid + 文件名解决
    文件名称或普通表单项乱码问题,两种方式解决
    request.setcharacterEncoding("uft-8") //优先级低
    ServletFileUpload的方法public void setHeaderEncoding(String encoding) //优先级高
  3. 目录打散
    不能再一个目录下存放过多的文件,解决方法:哈希打散,获取文件名的hashCode,将其转换成16进制,然后取前2位用来生成二级目录。例如:1A2B3C4D则取1A生成/1/A来保存文件。
    代码如下:

    1
    2
    3
    4
    int hCode = filename.hashCode();
    String hex = Integer.toHexString(hCode); //转换成16进制
    File dirFIle = new File(path, charAt(0) + "/" + charAt(1)); //构建文件保存目录,其中path为保存文件的根目录
    dirFile.mkdirs(); //生成目录链
  4. 上传文件大小限制
    单个文件大小限制,setFileSizeMax(long fileSizeMax),当上传文件的大小超过指定的大小时会抛出异常
    整个请求所有文件大小限制,setSizeMax(long SizeMax),当请求上传的所有文件的总大小超过指定的大小时会抛出异常
    且这两个方法都必须在parseRequest()方法之前调用。

  5. 缓存大小与临时目录
    缓存大小默认是10kb,超出10kb就往硬盘上保存。
    往硬盘上暂时保存的目录即缓存目录。
    设置缓存大小和临时目录:使用DsikFIleItemFactory的有参构造器 DiskFileItemFactory(int sizeThreshold, File repository),第一个参数为缓存大小(字节),第二个参数为临时目录。
    More info: Deployment