文件上传组件ApacheCommonsFileUpload应用指南.docx
- 文档编号:18246147
- 上传时间:2023-08-14
- 格式:DOCX
- 页数:25
- 大小:155.50KB
文件上传组件ApacheCommonsFileUpload应用指南.docx
《文件上传组件ApacheCommonsFileUpload应用指南.docx》由会员分享,可在线阅读,更多相关《文件上传组件ApacheCommonsFileUpload应用指南.docx(25页珍藏版)》请在冰点文库上搜索。
文件上传组件ApacheCommonsFileUpload应用指南
ApacheCommonsFileUpload
应用指南
前言
几乎每一个Web应用中都需要为用户提供文件上传的功能,例如,QQ空间、各种博客的相册、论坛的附件、个人头像等。
对文件上传功能,在浏览器端提供了较好的支持,只要将FORM表单的enctype属性设置为“multipart/form-data”,method属性设置为“post”即可;但在Web服务器端获取通过浏览器上传的文件数据(二进制输入流),需要进行复杂的编程处理。
为了简化文件上传的的处理,一些公司和组织专门开发了文件上传组件。
其中,Apache文件上传组件得到了广泛的传播和应用。
我们将详细介绍如何使用Apache文件上传组件进行文件上传实现。
1获取上传组件
使用ApacheCommonsFileupload文件上传组件需要两个类库文件:
1)commons-fileupload-1.2.2.jar
2)commons-io-1.4.jar
第一步:
下载commons-fileupload-1.2.2.jar。
在浏览器中输入http:
//commons.apache.org/fileupload/打开ApacheCommonsFileupload文件上传组件主页面,在Downloading栏目中点击任意一个版本号后面的“here”超级链接,可以打开当前最新版本的ApacheCommonsFileupload文件上传组件下载页面,(2010-08-28为止的可下载最新版本是1.2.2版)。
也可以直接输入http:
//commons.apache.org/fileupload/download_fileupload.cgi打开最新版本下载页面。
主页面
当前最新版本的下载页面
在当前最新版本的下载页面,提供二进制可执行版本(Binares)和源程序版本(Source)两种文件的下载,每一种文件都有两种压缩格式:
1).zip,适用windows操作系统
2).tar.gz,适用linux和unix操作系统
我们这里选择下载commons-fileupload-1.2.2-bin.zip文件。
解压后得到如下目录结构:
commons-fileupload-1.2.2(根目录)
-----lib(类库目录)
-----commons-fileupload-1.2.2.jar(我们要用的二进制类库)
-----site(包括ApacheCommonsFileupload组件站点所有页面文件)
-----apidocs(API文档目录,API文档链接可以在下面的首页中找到,也可以直接打开此目录,点击index.html打开API文档)
-----index.html(站点首页)
第二步:
下载commons-io-1.4.jar。
在浏览器中输入http:
//commons.apache.org/io/打开ApacheCommonsIO的主页,点击左侧菜单选项中的Download超级链接,打开当前最新版本下载页面(http:
//commons.apache.org/io/download_io.cgi),选择下载commons-io-1.4-bin.zip文件,解压缩在根目录中即可得到commons-io-1.4.jar。
到这里,我们就准备好了文件上传所需要的需要类库文件了。
2FileUpload如何工作?
在最初的 http 协议中,没有上传文件方面的功能。
RFC1867("Form-basedFileUploadinHTML".)为 http 协议添加了这个功能。
客户端的浏览器,如 Microsoft IE, Mozila, Opera 等,按照此规范将用户指定的文件发送到服务器。
服务器端的网页程序,如 php, asp, jsp 等,可以按照此规范,解析出用户发送来的文件。
2.1客户端
简单来说,RFC1867规范要求http协议增加了file类型的input标签,用于浏览需要上传的文件。
同时要求FORM表单的enctype属性设置为“multipart/form-data”,method属性设置为“post”即可,下面是我们文件上传页面的表单代码:
文本1:
文件2:
文件1:
文件2:
文件2:
2.2服务器端
一个文件上传请求的消息实体由一系列根据RFC1867("Form-basedFileUploadinHTML".)编码的项目(文本参数和文件参数)组成。
自己编程来解析获取这些数据是非常麻烦的,还需要了解RFC1867规范对请求数据编码的相关知识。
FileUpload可以帮助我们解析这样的请求,将每一个项目封装成一个实现了FileItem接口的对象,并以列表的形式返回。
所以,我们只需要了解FileUpload的API如何使用即可,不用管它们的底层实现。
让我们来看一个简单文件上传处理代码:
DiskFileItemFactoryfactory=newDiskFileItemFactory();
ServletFileUploaduploader=newServletFileUpload(factory);
List
if(item.isFormField()){
//处理普通表单域
Stringfield=item.getFieldName();//表单域名
Stringvalue=item.getString("GBK");
}else{
//将临时文件保存到指定目录
StringfileName=item.getName();//文件名称
Stringfilepath="您希望保存的目录/"+fileName;
item.write(newFile(filepath));//执行保存
}
怎么样?
简单吧!
下面我们来继续了解一些必须了解的API。
FileItem接口
mons.fileupload.disk.DiskFileItem实现了FileItem接口,用来封装单个表单字段元素的数据。
通过调用FileItem定义的方法可以获得相关表单字段元素的数据。
我们不需要关心DiskFileItem的具体实现,在程序中可以采用FileItem接口类型来对DiskFileItem对象进行引用和访问。
FileItem类还实现了Serializable接口,以支持序列化操作。
下图是一个文件上传表单:
上图表单提交的http数据包的内容:
POST/demo/servlet/SimpleUploadHTTP/1.1
Accept:
image/gif,image/x-xbitmap,image/jpeg,image/pjpeg,application/x-shockwave-flash,application/msword,application/vnd.ms-excel,application/vnd.ms-powerpoint,*/*
Referer:
http:
//127.0.0.1:
8080/demo/simpleUpload.jsp
Accept-Language:
zh-cn
Content-Type:
multipart/form-data;boundary=---------------------------7da1772c5504c6
UA-CPU:
x86
Accept-Encoding:
gzip,deflate
User-Agent:
Mozilla/4.0(compatible;MSIE7.0;WindowsNT5.1;.NETCLR2.0.50727)
Host:
127.0.0.1:
8080
Content-Length:
184423
Connection:
Keep-Alive
Cache-Control:
no-cache
Cookie:
JSESSIONID=BD8E58E5BAD9B559C0262077FB5E0B4E
-----------------------------7da1772c5504c6
Content-Disposition:
form-data;name="text1"
郑州蜂鸟科技有限公司
-----------------------------7da1772c5504c6
Content-Disposition:
form-data;name="text2"
申林
-----------------------------7da1772c5504c6
Content-Disposition:
form-data;name="file1";filename="C:
\DocumentsandSettings\AllUsers\Documents\MyPictures\示例图片\Bluehills.jpg"
Content-Type:
image/pjpeg
大量二进制数据内容,无法复制…….
-----------------------------7da1772c5504c6
Content-Disposition:
form-data;name="file2";filename="C:
\DocumentsandSettings\AllUsers\Documents\MyPictures\示例图片\Sunset.jpg"
Content-Type:
image/pjpeg
大量二进制数据内容,无法复制…….
-----------------------------7da1772c5504c6
Content-Disposition:
form-data;name="file3";filename="C:
\DocumentsandSettings\AllUsers\Documents\MyPictures\示例图片\Waterlilies.jpg"
Content-Type:
image/pjpeg
大量二进制数据内容,无法复制…….
从第一行,也就是请求行,我们可以看出这是一个post请求。
在请求头部部分,我们可以看到这样一个头部信息:
Content-Type:
multipart/form-data;boundary=---------------------------7da1772c5504c6
其中红色部分说明该请求是一个multipart/form-data类型即多媒体类型的请求。
蓝色部分boundary的值定义了一个字段分隔界线。
在消息体部分可以看出每个表单字段元素数据之间采用字段分隔界线进行分割,两个分隔界线间的内容称为一个分区,每个分区中的内容包括两部分,一部分是对表单字段元素进行描述的描述头,另外一部分是表单字段元素的主体内容。
通过对比描述头,我们可以很容易区分文本字段和文件字段。
不管是文件字段还是文本字段,都有name属性,即该字段作为一个表单域的名字。
而文件字段还有filename,即上传文件本身的名字。
另外,还有conten-type属性用于指明文件的类型。
每一个表单字段,不管它是文本还是文件,都被封装成FileItem对象,我们称之为文件项,当文件项数据内容尺寸小于DiskFileItemFactory的sizeThreshold属性设置的临界值时,直接保存在内存中;否则,将数据流以临时文件的形式,保存在DiskFileItemFactory的repository属性指定的临时目录中。
临时文件名形如“upload_00000005(八位或八位以上的数字).tmp”。
FileItem类内部提供了维护临时文件名中的数值不重复的机制,以保证了临时文件名的唯一性。
另外,如何保证临时文件能被及时清除,释放宝贵的系统资源,是非常重要的,我们将在后面讲解。
FileItem类常用的方法:
1.booleanisFormField()方法
isFormField方法用于判断FileItem类对象封装的数据是一个普通文本表单字段,还是一个文件表单字段,如果是普通表单字段则返回true,否则返回false。
2.StringgetName()方法
getName方法用于获得文件上传字段中的文件名,即表单字段元素描述头中的filename属性值,如“C:
\DocumentsandSettings\AllUsers\Documents\MyPictures\示例图片\Sunset.jpg”。
如果FileItem类对象对应的是普通表单字段,getName方法将返回null。
即使用户没有通过网页表单中的文件字段传递任何文件,但只要设置了文件表单字段的name属性,浏览器也会将文件字段的信息传递给服务器,只是文件名和文件内容部分都为空,但这个表单字段仍然对应一个FileItem对象,此时,getName方法返回结果为空字符串"",读者在调用Apache文件上传组件时要注意考虑这个情况。
注意:
上面的数据包是通过IE提交,所以是完整的路径和名称。
如C:
\DocumentsandSettings\AllUsers\Documents\MyPictures\示例图片\Sunset.jpg。
如果是其它浏览器,如火狐和Chromium,则仅仅是名字,没有路径,如Sunset.jpg。
3.StringgetFieldName()方法
getFieldName方法用于返回表单字段元素描述头的name属性值,也是表单标签name属性的值。
例如“name=file1”中的“file1”。
4.voidwrite(Filefile)方法
write方法用于将FileItem对象中保存的主体内容保存到某个指定的文件中。
如果FileItem对象中的主体内容是保存在某个临时文件中,该方法顺利完成后,临时文件有可能会被清除。
该方法也可将普通表单字段内容写入到一个文件中,但它主要用途是将上传的文件内容保存在本地文件系统中。
5.StringgetString()方法
getString方法用于将FileItem对象中保存的数据流内容以一个字符串返回,它有两个重载的定义形式:
publicjava.lang.StringgetString()
publicjava.lang.StringgetString(java.lang.String encoding)
throwsjava.io.UnsupportedEncodingException
前者使用缺省的字符集编码将主体内容转换成字符串,后者使用参数指定的字符集编码将主体内容转换成字符串。
如果在读取普通表单字段元素的内容时出现了中文乱码现象,请调用第二个getString方法,并为之传递正确的字符集编码名称。
6.StringgetContentType()方法
getContentType方法用于获得上传文件的类型,即表单字段元素描述头属性“Content-Type”的值,如“image/jpeg”。
如果FileItem类对象对应的是普通表单字段,该方法将返回null。
7.booleanisInMemory()方法
isInMemory方法用来判断FileItem对象封装的数据内容是存储在内存中,还是存储在临时文件中,如果存储在内存中则返回true,否则返回false。
8.voiddelete()方法
delete方法用来清空FileItem类对象中存放的主体内容,如果主体内容被保存在临时文件中,delete方法将删除该临时文件。
尽管当FileItem对象被垃圾收集器收集时会自动清除临时文件,但及时调用delete方法可以更早的清除临时文件,释放系统存储资源。
另外,当系统出现异常时,仍有可能造成有的临时文件被永久保存在了硬盘中。
9.InputStreamgetInputStream()方法
以流的形式返回上传文件的数据内容。
10.longgetSize()方法
返回该上传文件的大小(以字节为单位)。
DiskFileItemFactory类
将请求消息实体中的每一个项目封装成单独的DiskFileItem(FileItem接口的实现)对象的任务由mons.fileupload.FileItemFactory 接口的默认实现mons.fileupload.disk.DiskFileItemFactory来完成。
当上传的文件项目比较小时,直接保存在内存中(速度比较快),比较大时,以临时文件的形式,保存在磁盘临时文件夹(虽然速度慢些,但是内存资源是有限的)。
属性
1)publicstaticfinalintDEFAULT_SIZE_THRESHOLD:
将文件保存在内存还是磁盘临时文件夹的默认临界值,值为10240,即10kb。
2)privateFilerepository:
用于配置在创建文件项目时,当文件项目大于临界值时使用的临时文件夹,默认采用系统默认的临时文件路径,可以通过系统属性java.io.tmpdir获取。
如下代码:
System.getProperty("java.io.tmpdir");
3)privateintsizeThreshold:
用于保存将文件保存在内存还是磁盘临时文件夹的临界值
构造方法
1)publicDiskFileItemFactory():
采用默认临界值和系统临时文件夹构造文件项工厂对象。
2)publicDiskFileItemFactory(int sizeThreshold,File repository):
采用参数指定临界值和系统临时文件夹构造文件项工厂对象。
FileItemcreateItem()方法
根据DiskFileItemFactory相关配置将每一个请求消息实体项目创建成DiskFileItem 实例,并返回。
该方法从来不需要我们亲自调用,FileUpload组件在解析请求时内部使用。
voidsetSizeThreshold(int sizeThreshold)
Apache文件上传组件在解析上传数据中的每个字段内容时,需要临时保存解析出的数据,以便在后面进行数据的进一步处理(保存在磁盘特定位置或插入数据库)。
因为Java虚拟机默认可以使用的内存空间是有限的,超出限制时将会抛出“java.lang.OutOfMemoryError”错误。
如果上传的文件很大,例如800M的文件,在内存中将无法临时保存该文件内容,Apache文件上传组件转而采用临时文件来保存这些数据;但如果上传的文件很小,例如600个字节的文件,显然将其直接保存在内存中性能会更加好些。
setSizeThreshold方法用于设置是否将上传文件已临时文件的形式保存在磁盘的临界值(以字节为单位的int值),如果从没有调用该方法设置此临界值,将会采用系统默认值10KB。
对应的getSizeThreshold()方法用来获取此临界值。
voidsetRepository(File repository)
setRepositoryPath方法用于设置当上传文件尺寸大于setSizeThreshold方法设置的临界值时,将文件以临时文件形式保存在磁盘上的存放目录。
有一个对应的获得临时文件夹的FilegetRespository()方法。
注意:
当从没有调用此方法设置临时文件存储目录时,默认采用系统默认的临时文件路径,可以通过系统属性java.io.tmpdir获取。
如下代码:
System.getProperty("java.io.tmpdir");
Tomcat系统默认临时目录为“
ServletFileUpload类
mons.fileupload.servlet.ServletFileUpload类是Apache文件上传组件处理文件上传的核心高级类(所谓高级就是不需要管底层实现,暴露给用户的简单易用的接口)。
使用其 parseRequest(HttpServletRequest)方法可以将通过表单中每一个HTML标签提交的数据封装成一个FileItem对象,然后以List列表的形式返回。
使用该方法处理上传文件简单易用。
如果你希望进一步提高新能,你可以采用getItemIterator方法,直接获得每一个文件项的数据输入流,对数据做直接处理。
在使用ServletFileUpload对象解析请求时需要根据DiskFileItemFactory对象的属性sizeThreshold(临界值)和repository(临时目录)来决定将解析得到的数据保存在内存还是临时文件中,如果是临时文件,保存在哪个临时目录中?
。
所以,我们需要在进行解析工作前构造好DiskFileItemFactory对象,通过ServletFileUpload对象的构造方法或setFileItemFactory()方法设置ServletFileUpload对象的fileItemFactory属性。
ServletFileUpload继承结构:
java.lang.Object
|—mons.fileupload.FileUploadBase
|—mons.fileupload.FileUpload
|—mons.fileupload.servlet.ServletFileUpload
构造方法:
1)publicServletFileUpload():
构造一个未初始化的实例,需要在解析请求之前先调用setFileItemFactory()方法设置fileItemFactory属性。
2)publicServletFileUpload(FileItemFactory fileItemFactory):
构造一个实例,并根据参数指定的FileItemFactory 对象,设置fileItemFactory属性。
ServletFileUpload类常用方法:
1.publicvoidsetSizeMax(longsi
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 文件 上传 组件 ApacheCommonsFileUpload 应用 指南