FileUpload应用指南

Creative Commons License
本作品采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。

 

 

当客户端浏览器指定enctype为multipart/form-data提交表单时,HTTP服务器上与该请求对应的servlet(Servlet类或JSP网页)将无法通过request对象的getParameter()方法取得表单域的属性值。如果对HTTP协议熟悉的话,我们可以对multipart/form-data数据流进行分析,取出其中有用的信息。但这样做完全没有必要,Apache的Commons FileUpload程序包已经替我们完成了这项复杂的工作。

基本用法

FileUpload API提供了两种核心处理类:PortletFileUploadServletFileUpload,本文不对PortletFileUpload做详细描述。ServletFileUpload类有一个判断Content-Type是否为multipart/form-data的方法。同时提供了两种读取multipart/form-data数据的方式:数据流读取方式和临时文件读取方式。

判断是否是multipart/form-data

利用ServletFileUpload类的静态方法可以判断一个request的Content-Type是否是multipart/form-data。例:

 

数据流读取方式

通过无参构造器生成的ServletFileUpload对象使用的是数据流读取方式,可通过getItemIterator()方法取得每一个表单域的数据。如:

 

数据流读取方式是一种一次性的读取方式。一方面,upload对象只能对request的数据做一次性分析。也就是说,上文第5行只在第一次调用时有效。另一方面,分析数据只能读取一次,第二次读取时数据不存在。也就是说,上文第5行取到的FileItemIterator对象只能遍历一次,第二次遍历该对象时就无法取到数据了。

临时文件读取方式

通过有参构造器生成的ServletFileUpload对象使用的是临时文件读取方式,可通过parseRequest()方法取得表单域数据列表。如:

 

同样,upload对象只能对request的数据做一次性分析。但与数据流读取方式相对应的是,临时文件读取方式中解析出来的数据被缓存到缓冲文件中,可对缓存数据多次读取,并且在必要的情况下可以修改缓存的内容。

FileUpload API出于下面的考虑实现了临时文件读取方式

  • 如果上传内容比较小,则将其直接放入到内存中进行管理;
  • 较大的上传内容将保存到磁盘上的一个临时文件夹中;
  • 非常大的上传内容将被忽视。

默认情况下,FileUpload对数据大小的要求是:

  • 小于10K的数据直接放到内存中管理;
  • 大于10K的数据保存到系统临时目录中(系统临时目录是System.getProperty("java.io.tmpdir")的返回值);
  • 所有的数据都不被忽视,即使这个数据非常大。

如何改变这些默认值呢?

如何控制FileUpload

作为核心应用对象,ServletFileUpload可以设置以下属性:


sizeMax
    限制整个multipart/form-data数据的字节大小。默认值-1,表示无限制。
fileSizeMax
    限制每个文件表单域中数据的字节大小。默认值-1,表示无限制。
headerEncoding
    指定每个multipart头部信息的编码方式。默认为NULL,如果该值为NULL,则使用request中的characterEncoding值,如果characterEncoding为NULL,则使用系统默认的字符集编码方式。

 

设置属性的样例如下:

 

如果FileUpload使用临时文件读取方式,还可以为工厂类设置以下属性:

sizeThreshold
    限制将文件表单域中的数据保存到内存的临界字节大小。默认为10K字节长度,数据小于10K字节则直接保存在内存中;数据大于10K字节则保存在临时文件夹中。
repository
    临时文件夹的位置。默认为System.getProperty("java.io.tmpdir")的返回值。

 

例如改变临时文件夹的位置到“C:/tmp”的方法如下:

 

附1:FileUpload附加信息

官方网站
http://commons.apache.org/fileupload/
核心JAR包
commons-fileupload-1.2.1.jar
依赖JAR包
commons-io-1.4.jar

 

附2:HTTP请求数据结构

当客户端浏览器使用GBK编码提交了下面这样一个表单时...

 

一个数据内容如下的HTTP请求将会发送到HTTP服务器上。

POST /test/hello.html HTTP/1.1
Referer: http://localhost:9000/test/
Accept-Language: zh-cn
Content-Type: multipart/form-data; boundary=---------------------------7d91f4b304fc
Accept-Encoding: gzip, deflate
Host: localhost:9000
Content-Length: 301
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: JSESSIONID=763D1C03A83AE30CCFBA88F42465F598

 

-----------------------------7d91f4b304fc
Content-Disposition: form-data; name="name"

 

中国
-----------------------------7d91f4b304fc
Content-Disposition: form-data; name="file"; filename="C:/test.txt"
Content-Type: text/plain

 

这是测试文档的内容
-----------------------------7d91f4b304fc--

[end]

每一个multipart的头部信息用红字表示;其编码所用的字符集是表单所在网页在浏览器上显示时所使用的字符集。
如果multipart是一般表单域,如上例中的name表单域,其内容一般为字符串,字符串编码所用的字符集与multipart的头部信息相同。
如果multipart是文件表单域,如上例中的file表单域,其内容为文件数据的二进制表现形成,内容格式由multipart的头部信息指定。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Jsp+Servlet的文件上传 index.jsp <%@ page contentType="text/html; charset=GBK"%> <html> <head> <body> <form method="post" action="upload.jsp" name="pw" enctype="multipart/form-data"> 文件一 <input type="file" name="file1"> <br> 文件二 <input type="file" name="file2"> <br> 文件三 <input type="file" name="file3"> <br> <input TYPE="submit" value="确定上传"> </form> </body> </html> upload.jsp <%@ page language="java" import="fileUpload.*"%> <%@ page contentType="text/html;charset=gb2312"%> <%@ page errorPage="error.jsp"%> <%@ page import="java.io.File,java.util.*,java.text.*"%> <!-- 初始化一个upBean--> <jsp:useBean id="myUpload" scope="page" class="fileUpload.upBean" /> <% //初始化工作 myUpload.initialize(pageContext); //设定允许的文件后缀名 //myUpload.setAllowedExtList("gif,jpg"); //设定允许上传的文件类型 //gif:gif //jpg:pjpeg //text:plain //html:html //doc:msword // myUpload.setAllowedFileTypeList("gif,jpg"); //设定是否允许覆盖服务器上的同名文件 myUpload.setIsCover(false); //设定允许上传文件的总大小 //myUpload.setTotalMaxFileSize(1000000); //设定单个文件大小的限制 //myUpload.setMaxFileSize(100000); String myName = new String(""); //设定上传的物理路径 myUpload.setRealPath(application.getRealPath(File.separator + "upload")); try { //将所有数据导入组件的数据结构中 myUpload.upload(); } catch (Exception e) { throw e; } //得到所有上传的文件 files myFiles = myUpload.getFiles(); String[] sourceName = new String[myFiles.getCount()]; //文件的原始文件名数组 //将文件保存到服务器 try { for (int i = 0; i < myFiles.getCount(); i++) { Date date = new Date(); DateFormat df = new SimpleDateFormat("yyyyMMddHHmmsszzz"); String name = System.currentTimeMillis() + ""; // myName="myName"; // myName=myName+"_"+i+"."+myFiles.getFile(i).getExtName(); myName = name + "." + myFiles.getFile(i).getExtName(); //保存的图片名称 sourceName[i] = myFiles.getFile(i).getName(); myFiles.getFile(i).setName(myName); //有两种保存方法,一种是保存在myUpload.setRealPath()的设定路径中,使用saveAs(),一种是另外保存到其他文件夹,使用.saveAs(String realPath) myFiles.getFile(i).saveAs(); Thread.sleep(50); } } catch (Exception e) { throw e; } %> <html> <head> <title>上传结果</title> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <meta http-equiv="expires" content="fri,30 dec 1999 00:00:00 gmt"> <meta name="author" content="fredwebs@sina.com"> <link rel='stylesheet' href='style.css' type='text/css'> </head> <body bgcolor="#999999" style="margin: 0;"> 上传成功! </table> </body> </html>
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值