Apache FileUpload 文件上传组件API解读-2
来源:互联网 发布:地暖好吗知乎 编辑:程序博客网 时间:2024/06/07 12:53
1.RFC1867协议
最初的
为
户指定的文件发送到服务器。服务器端的网页程序,如
发送来的文件。
2.1客户端
简单来说,RFC1867规范要求http协议增加了file类型的input标签,用于浏览需要上传的文件。同时
要求FORM表单的enctype属性设置为“multipart/form-data”,method属性设置为“post”即可,下面是我们文
件上传页面的表单代码:
<form
method="post">
文本1:<input
文件2:<input
文件1:<input
文件2:<input
文件2:<input
<input
</form>
2.2
一个文件上传请求的消息实体由一系列根据
(文本参数和文件参数)组成。自己编程来解析获取这些数据是非常麻烦的,还需要了解RFC1867规范对请
求数据编码的相关知识。FileUpload
接口的对象,并以列表的形式返回。所以,我们只需要了解FileUpload的API如何使用即可,不用管它们的底
层实现。让我们来看一个简单文件上传处理代码:
DiskFileItemFactory
ServletFileUpload
List<FileItem>
if
//
String
String
}
//将临时文件保存到指定目录
String
String
item.write(new
}
FileItem接口
org.apache.commons.fileupload.disk.DiskFileItem实现了FileItem接口,用来封装单个表单字段元素的
数据。通过调用FileItem
体实现,在程序中可以采用FileItem接口类型来对DiskFileItem对象进行引用和访问。FileItem类还实现了
Serializable接口,以支持序列化操作。
下图是一个文件上传表单:
...............
...............
...............
上图表单提交的http数据包的内容:
POST
Accept:
application/vnd.ms-excel,
Referer:
Accept-Language:
Content-Type:
UA-CPU:
Accept-Encoding:
User-Agent:
Host:
Content-Length:
Connection:
Cache-Control:
Cookie:
-----------------------------7da1772c5504c6
Content-Disposition:
郑州蜂鸟科技有限公司
-----------------------------7da1772c5504c6
Content-Disposition:
申林
-----------------------------7da1772c5504c6
Content-Disposition:
Documents\My
Content-Type:
大量二进制数据内容,无法复制
-----------------------------7da1772c5504c6
Content-Disposition:
Documents\My
Content-Type:
大量二进制数据内容,无法复制
-----------------------------7da1772c5504c6
Content-Disposition:
Documents\My
Content-Type:
大量二进制数据内容,无法复制
从第一行,也就是请求行,我们可以看出这是一个post请求。在请求头部部分,我们可以看到这样
一个头部信息:
Content-Type:
其中红色部分说明该请求是一个multipart/form-data类型即多媒体类型的请求。蓝色部分boundary的值定义了一个字段分隔界线。
在消息体部分可以看出每个表单字段元素数据之间采用字段分隔界线进行分割,两个分隔界线间的内容称为一个分区,每个分区中的内容包括两部分,一部分是对表单字段元素进行描述的描述头,另外一部分是表单字段元素的主体内容。
通过对比描述头,我们可以很容易区分文本字段和文件字段。不管是文件字段还是文本字段,都有name属性,即该字段作为一个表单域的名字。而文件字段还有filename,即上传文件本身的名字。另外,还有conten-type属性用于指明文件的类型。
每一个表单字段,不管它是文本还是文件,都被封装成
FileItem类内部提供了维护临时文件名中的数值不重复的机制,以保证了临时文件名的唯一性。另外,如何保证临时文件能被及时清除,释放宝贵的系统资源,是非常重要的,我们将在后面讲解。
FileItem类常用的方法:
1.
isFormField方法用于判断FileItem类对象封装的数据是一个普通文本表单字段,还是一个文件表单字
段,如果是普通表单字段则返回true,否则返回false。
2.
getName方法用于获得文件上传字段中的文件名,即表单字段元素描述头中的filename属性值,如“C:\Documents
如果FileItem类对象对应的是普通表单字段,getName方法将返回null。即使用户没有通过网页表单中的文件字段传递任何文件,但只要设置了文件表单字段的name属性,浏览器也会将文件字段的信息传递给服务器,只是文件名和文件内容部分都为空,但这个表单字段仍然对应一个FileItem对象,此时,getName方法返回结果为空字符串"",读者在调用Apache文件上传组件时要注意考虑这个情况。
注意:上面的数据包是通过IE提交,所以是完整的路径和名称。如
C:\Documents
器,如火狐和Chromium,则仅仅是名字,没有路径,如Sunset.jpg。
3.
getFieldName方法用于返回表单字段元素描述头的name属性值,也是表单标签name属性的值。例
如“name=file1”中的“file1”。
4.
write方法用于将FileItem对象中保存的主体内容保存到某个指定的文件中。如果FileItem对象中的主
体内容是保存在某个临时文件中,该方法顺利完成后,临时文件有可能会被清除。该方法也可将普通
表单字段内容写入到一个文件中,但它主要用途是将上传的文件内容保存在本地文件系统中。
5.
getString方法用于将FileItem对象中保存的数据流内容以一个字符串返回,它有两个重载的定义形式:
public
public
throws
前者使用缺省的字符集编码将主体内容转换成字符串,后者使用参数指定的字符集编码将主体内容
转换成字符串。如果在读取普通表单字段元素的内容时出现了中文乱码现象,请调用第二个
getString方法,并为之传递正确的字符集编码名称。
6.
getContentType
如“image/jpeg”。如果FileItem类对象对应的是普通表单字段,该方法将返回null。
7.
isInMemory方法用来判断FileItem对象封装的数据内容是存储在内存中,还是存储在临时文件中,
如果存储在内存中则返回true,否则返回false。
8.
delete方法用来清空FileItem类对象中存放的主体内容,如果主体内容被保存在临时文件中,
delete方法将删除该临时文件。
尽管当FileItem对象被垃圾收集器收集时会自动清除临时文件,但及时调用delete方法可以更早的
清除临时文件,释放系统存储资源。另外,当系统出现异常时,仍有可能造成有的临时文件被永久
保存在了硬盘中。
9.
10.
返回该上传文件的大小(以字节为单位)。
DiskFileItemFactory类
将请求消息实体中的每一个项目封装成单独的
由
存在内存中(速度比较快),比较大时,以临时文件的形式,保存在磁盘临时文件夹(虽然速度慢些,但是内存资源是有限的)。
属性
1)
将文件保存在内存还是磁盘临时文件夹的默认临界值,值为10240,即10kb。
2)
用于配置在创建文件项目时,当文件项目大于临界值时使用的临时文件夹,默认采用系统默认的临时文件路径,可以通过系统属性
System.getProperty("java.io.tmpdir");
3)
用于保存将文件保存在内存还是磁盘临时文件夹的临界值
构造方法
1)
采用默认临界值和系统临时文件夹构造文件项工厂对象。
2)
采用参数指定临界值和系统临时文件夹构造文件项工厂对象。
FileItem
根据DiskFileItemFactory相关配置将每一个请求消息实体项目创建
该方法从来不需要我们亲自调用,FileUpload组件在解析请求时内部使用。
void
Apache文件上传组件在解析上传数据中的每个字段内容时,需要临时保存解析出的数据,以便
在后面进行数据的进一步处理(保存在磁盘特定位置或插入数据库)。因为Java虚拟机默认可以使
用的内存空间是有限的,超出限制时将会抛出“java.lang.OutOfMemoryError”错误。如果上传的文件
很大,例如800M的文件,在内存中将无法临时保存该文件内容,Apache文件上传组件转而采用临时
文件来保存这些数据;但如果上传的文件很小,例如600个字节的文件,显然将其直接保存在内存中
性能会更加好些。
setSizeThreshold方法用于设置是否将上传文件已临时文件的形式保存在磁盘的临界值(以字节
为单位的int值),如果从没有调用该方法设置此临界值,将会采用系统默认值10KB。对应的
getSizeThreshold()
void
setRepositoryPath方法用于设置当上传文件尺寸大于setSizeThreshold方法设置的临界值时,将文件以
临时文件形式保存在磁盘上的存放目录。有一个对应的获得临时文件夹的
注意:当从没有调用此方法设置临时文件存储目录时,默认采用系统默认的临时文件路径,可以
通过系统属性
System.getProperty("java.io.tmpdir");
Tomcat系统默认临时目录为“<tomcat安装目录>/temp/”。
ServletFileUpload
org.apache.commons.fileupload.servlet.ServletFileUpload类是Apache文件上传组件处理文件上传的
核心高级类(所谓高级就是不需要管底层实现,暴露给用户的简单易用的接口)。
使用其
成一个FileItem对象,然后以List列表的形式返回。使用该方法处理上传文件简单易用。
如果你希望进一步提高新能,你可以采用
入流,对数据做直接处理。
在使用ServletFileUpload对象解析请求时需要根据DiskFileItemFactory对象的属性
界值)和repository(临时目录)
文件,保存在哪个临时目录中?。
所以,我们需要在进行解析工作前构造好DiskFileItemFactory对象,通过ServletFileUpload对象的构造方法或setFileItemFactory()方法设置
fileItemFactory属性。
ServletFileUpload继承结构:
java.lang.Object
|—org.apache.commons.fileupload.FileUploadBase
|—org.apache.commons.fileupload.servlet.ServletFileUpload
构造方法:
1)
构造一个未初始化的实例,需要在解析请求之前先调用setFileItemFactory()方法设置
2)
构造一个实例,并根据参数指定的FileItemFactory
ServletFileUpload类常用方法:
1.
setSizeMax方法继承自FileUploadBase类,用于设置请求消息实体内容(即所有上传数据)的最大
尺寸限制,以防止客户端恶意上传超大文件来浪费服务器端的存储空间。其参数是以字节为单位的
long型数字。
在请求解析的过程中,如果请求消息体内容的大小超过了setSizeMax方法的设置值,将会抛出
FileUploadBase内部定义的SizeLimitExceededExcepti
org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededExcepti
the
maximum
该方法有一个对应的读方法:public
2.
setFileSizeMax方法继承自FileUploadBase类,用于设置单个上传文件的最大尺寸限制,以防止客户
端恶意上传超大文件来浪费服务器端的存储空间。其参数是以字节为单位的long型数字。该方法有一个
对应的读方法:public
在请求解析的过程中,如果单个上传文件的大小超过了setFileSizeMax方法的设置值,将会抛出
FileUploadBase内部定义的FileSizeLimitExceededExc
org.apache.commons.fileupload.FileUploadBase$FileSizeLimitExceededExc
3.
parseRequest
方法。它解析出FORM表单中的每个字段的数据,并将它们分别包装成独立的FileItem对象,然后将这
些FileItem对象加入进一个List类型的集合对象中返回。
该方法抛出FileUploadException异常来处理诸如文件尺寸过大、请求消息中的实体内容的类型不
是“multipart/form-data”、IO异常、请求消息体长度信息丢失等各种异常。每一种异常都是
FileUploadException的一个子类型。
4.
getItemIterator方法和parseRequest
器,该迭代器中保存的不是FileItem对象,而是FileItemStream
你可以采用
是问题,你希望代码简单,则采用parseRequest方法即可。
5.
isMultipartContent方法方法用于判断请求消息中的内容是否是“multipart/form-data”类型,是则返
回true,否则返回false。isMultipartContent方法是一个静态方法,不用创建ServletFileUpload类的实例对
象即可被调用。
6.
方法继承自FileUpload类,用于设置和读取fileItemFactory属性。
7.
设置文件上传进度监听器。关于监听器的具体内容,将在后面学习。该方法有一个对应的读取
方法:ProgressListener
8.public
在文件上传请求的消息体中,除了普通表单域的值是文本内容以外,文件上传字段中的文件路
径名也是文本,在内存中保存的是它们的某种字符集编码的字节数组,Apache文件上传组件在读取
这些内容时,必须知道它们所采用的字符集编码,才能将它们转换成正确的字符文本返回。
setHeaderEncoding方法继承自FileUploadBase类,用于设置上面提到的字符编码。如果没有设置,
则对应的读方法getHeaderEncoding()方法返回null,将采用HttpServletRequest设置的字符编码,如果
HttpServletRequest的字符编码也为null,则采用系统默认字符编码。可以通过一下语句获得系统默认
字符编码:
System.getProperty("file.encoding"));
- Apache FileUpload 文件上传组件API解读-2
- Apache FileUpload文件上传组件API解析
- Apache FileUpload文件上传组件API解析
- Apache FileUpload文件上传组件API解析
- Apache FileUpload文件上传组件API解析
- Apache FileUpload文件上传组件API解析
- Apache FileUpload文件上传组件API解析
- Apache FileUpload文件上传组件API解析
- 解析Apache FileUpload文件上传组件API
- Apache FileUpload文件上传组件API解析
- Apache FileUpload文件上传组件API解析
- Apache FileUpload文件上传组件API解析
- Using FileUpload(Apache文件上传组件)
- Apache FileUpload上传组件API解析(待续)
- 文件上传FileUpload组件
- FileUpload组件上传文件
- FileUpload组件上传文件
- Apache FileUpload文件上传
- 谈CSS的设计模式
- ES权威指南_05_Geolocation_03 Geo Aggs
- 使用Stanford CoreNLP工具包处理中文
- 与人沟通经验积累
- ES权威指南_05_Geolocation_04 Geo Shapes
- Apache FileUpload 文件上传组件API解读-2
- 设计模式之构造模式
- Java中CAS详解
- SQL Server 用户只看到自己有权限的库
- 比较Collection 和Collections的区别,Array与Arrays的区别
- thymeleaf模板部分知识(持续更新)
- ES权威指南_06_Modeling Your Data_01 Handling Relationships
- P1118 数字三角形(技巧)
- ES权威指南_06_Modeling Your Data_02 Nested Objects