日期:2014-05-17  浏览次数:20717 次

org.apache.commons.fileupload.DiskFileUpload使用

1.setSizeMax方法?
setSizeMax方法用于设置请求消息实体内容的最大允许大小,以防止客户端故意通过上传特大的文件来塞满服务器端的存储空间,单位为字节。?

2.setSizeThreshold方法?
Apache文件上传组件在解析和处理上传数据中的每个字段内容时,需要临时保存解析出的数据。因为Java虚拟机默认可以使用的内存空间是有限的(笔者测试不大于100M),超出限制时将会发生“java.lang.OutOfMemoryError”错误,如果上传的文件很大,例如上传800M的文件,在内存中将无法保存该文件内容,Apache文件上传组件将用临时文件来保存这些数据;但如果上传的文件很小,例如上传600个字节的文件,显然将其直接保存在内存中更加有效。setSizeThreshold方法用于设置是否使用临时文件保存解析出的数据的那个临界值,该方法传入的参数的单。?

3. setRepositoryPath方法?
setRepositoryPath方法用于设置setSizeThreshold方法中提到的临时文件的存放目录,这里要求使用绝对路径。其完整语法定义如下:?
public void setRepositoryPath(String repositoryPath)?
如果不设置存放路径,那么临时文件将被储存在"java.io.tmpdir"这个JVM环境属性所指定的目录中,tomcat 5.5.9将这个属性设置为了“<tomcat安装目录>/temp/”目录。?

4. parseRequest方法?
parseRequest 方法是DiskFileUpload类的重要方法,它是对HTTP请求消息进行解析的入口方法,如果请求消息中的实体内容的类型不是“multipart/form-data”,该方法将抛出FileUploadException异常。parseRequest 方法解析出FORM表单中的每个字段的数据,并将它们分别包装成独立的FileItem对象,然后将这些FileItem对象加入进一个List类型的集合对象中返回。parseRequest 方法的完整语法定义如下:?
public List parseRequest(HttpServletRequest req)?
parseRequest 方法还有一个重载方法,该方法集中处理上述所有方法的功能,其完整语法定义如下:?
parseRequest(HttpServletRequest req,int sizeThreshold,long sizeMax, String path)?
这两个parseRequest方法都会抛出FileUploadException异常。?
5. isMultipartContent方法?
isMultipartContent方法方法用于判断请求消息中的内容是否是“multipart/form-data”类型,是则返回true,否则返回false。isMultipartContent方法是一个静态方法,不用创建DiskFileUpload类的实例对象即可被调用,其完整语法定义如下:?
public static final boolean isMultipartContent(HttpServletRequest req)?
6. setHeaderEncoding方法?
由于浏览器在提交FORM表单时,会将普通表单中填写的文本内容传递给服务器,对于文件上传字段,除了传递原始的文件内容外,还要传递其文件路径名等信息,如后面的图1.3所示。不管FORM表单采用的是“application/x-www-form-urlencoded”编码,还是“multipart/form-data”编码,它们仅仅是将各个FORM表单字段元素内容组织到一起的一种格式,而这些内容又是由某种字符集编码来表示的。关于浏览器采用何种
字符集来编码FORM表单字段中的内容,请参看笔者编著的《深入体验java Web开发内幕——核心基础》一书中的第6.9.2的讲解,“multipart/form-data”类型的表单为表单字段内容选择字符集编码的原理和方式与“application/x-www-form-urlencoded”类型的表单是相同的。FORM表单中填写的文本内容和文件上传字段中的文件路径名在内存中就是它们的某种字符集编码的字节数组形式,Apache文件上传组件在读取这些内容时,必须知道它们所采用的字符集编码,才能将它们转换成正确的字符文本返回。?
对于浏览器上传给WEB服务器的各个表单字段的描述头内容,Apache文件上传组件都需要将它们转换成字符串形式返回,setHeaderEncoding 方法用于设置转换时所使用的字符集编码,其原理与笔者编著的《深入体验java Web开发内幕——核心基础》一书中的第6.9.4节讲解的ServletRequest.setCharacterEncoding方法相同。setHeaderEncoding 方法的完整语法定义如下:?
public void setHeaderEncoding(String encoding)?
其中,encoding参数用于指定将各个表单字段的描述头内容转换成字符串时所使用的字符集编码。?
注意:如果读者在使用Apache文件上传组件时遇到了中文字符的乱码问题,一般都是没有正确调用setHeaderEncoding方法的原因。?
1.2.3 FileItem类?
FileItem类用来封装单个表单字段元素的数据,一个表单字段元素对应一个FileItem对象,通过调用FileItem对象的方法可以获得相关表单字段元素的数据。FileItem是一个接口,在应用程序中使用的实际上是该接口一个实现类,该实现类的名称并不重要,程序可以采用FileItem接口类型来对它进行引用和访问,为了便于讲解,这里将FileItem实现类称之为FileItem类。FileItem类还实现了Serializable接口,以支持序列化操作。?
对于“multipart/form-data”类型的FORM表单,浏览器上传的实体内容中的每个表单字段元素的数据之间用字段分隔界线进行分割,两个分隔界线间的内容称为一个分区,每个分区中的内容可以被看作两部分,一部分是对表单字段元素进行描述的描述头,另外一部是表单字段元素的主体内容,如图1.3所示。?
图 1.3?
主体部分有两种可能性,要么是用户填写的表单内容,要么是文件内容。FileItem类对象实际上就是对图1.3中的一个分区的数据进行封装的对象,它内部用了两个成员变量来分别存储描述头和主体内容,其中保存主体内容的变量是一个输出流类型的对象。当主体内容的大小小于DiskFileUpload.setSizeThreshold方法设置的临界值大小时,这个流对象关联到一片内存,主体内容将会被保存在内存中。当主体内容的数据超过DiskFileUpload.setSizeThreshold方法设置的临界值大小时,这个流对象关联到硬盘上的一个临时文件,主体内容将被保存到该临时文件中。临时文件的存储目录由DiskFileUpload.setRepositoryPath方法设置,临时文件名的格式为“upload_00000005(八位或八位以上的数字).tmp”这种形式,FileItem类内部提供了维护临时文件名中的数值不重复的机制,以保证了临时文件名的唯一性。当应用程序将主体内容保存到一个指定的文件中时,或者在FileItem对象被垃圾回收器回收时,或者Java虚拟机结束时,Apache文件上传组件都会尝试删除临时文件,以尽量保证临时文件能被及时清除。?
下面介绍FileItem类中的几个常用的方法:?
1. isFormField方法?
isFormField方法用于判断FileItem类对象封装的数据是否属于一个普通表单字段,还是属于一个文件表单字段,如果是普通表单字段则返回true,否则返回false。该方法的完整语法定义如下:?
public boolean isFormField()?
2. getName方法?
getName方法用于获得文件上传字段中的文件名,对于图1.3中的第三个分区所示的描述头,getName方法返回的结果为字符串“C:\bg.gif”。如果FileItem类对象对应的是普通表单字段,getName方法将返回null。即使用户没有通过网页表单中的文件字段传递任何文件,但只要设置了文件表单字段的name属性,浏览器也会将文件字段的信息传递给服务器,只是文件名和文件内容部分都为空,但这个表单字段仍然对应一个FileItem对象,此时,getName方法返回结果为空字符串"",读者在调用Apache文件上传组件时要注意考虑这个情况。getName方法的完整语法定义如下:?
public String getName()?
注意:如果用户使用Windows系统上传文件,浏览器将传递该文件的完整路径,如果用户使用L