`
SIHAIloveYAN
  • 浏览: 124501 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类

Apache FileUpload介绍

 
阅读更多

Apache FileUpload组件

在最初的 http 协议中,没有上传文件方面的功能。RFC1867(”Form-based File Upload in HTML”.)为 http 协议添加了这个功能。客户端的浏览器,如 Microsoft IE, Mozila, Opera 等,按照此规范将用户指定的文件发送到服务器。服务器端的网页程序,如 php, asp, jsp 等,可以按照此规范,解析出用户发送来的文件。

1.1、客户端

简单来说,RFC1867规范要求http协议增加了file类型的input标签,用于浏览需要上传的文件。同时要求FORM表单的enctype属性设置为“multipart/form-data”,method属性设置为“post”即可,下面是我们文。
件上传页面的表单代码:

<form action="<%=request.getContextPath()%>/Upload3Servlet" 
 method="post" 
 enctype="multipart/form-data">
File1:<input type="file" name="file"/><br/>
Desc:<input type="text" name="desc"/><br/>
<input type="submit" value="提交"/>
</form>

1.2、服务器端
一个文件上传请求的消息实体由一系列根据 RFC1867(”Form-based File Upload in HTML”.)编码的项目(文本参数和文件参数)组成。自己编程来解析获取这些数据是非常麻烦的,还需要了解RFC1867规范对请求数据编码的相关知识。FileUpload 可以帮助我们解析这样的请求,将每一个项目封装成一个实现了FileItem接口的对象,并以列表的形式返回。所以,我们只需要了解FileUpload的API如何使用即可,不用管它们的底层实现。
让我们来看一个简单文件上传处理代码:

package cn.itcast.servlet;
import java.io.File;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
/**
 * 文件上传
 * @author <a href="mailto:wj@itcast.cn">王健</a>
 */
public class UploadServlet extends HttpServlet {
@SuppressWarnings("unchecked")
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
DiskFileItemFactory f = new DiskFileItemFactory();//磁盘对象
f.setRepository(new File("d:/a"));
//设置临时目录
f.setSizeThreshold(1024*8);
//8k的缓冲区,文件大于8K则保存到临时目录
ServletFileUpload upload = new ServletFileUpload(f);//声明解析request的对象
upload.setHeaderEncoding("UTF-8");
//处理文件名中文
upload.setFileSizeMax(1024 * 1024 * 5);// 设置每个文件最大为5M
upload.setSizeMax(1024 * 1024 * 10);// 一共最多能上传10M
String path = getServletContext().getRealPath("/imgs");//获取文件要保存的目录
try {
List<FileItem> list = upload.parseRequest(request);// 解析
for (FileItem ff : list) {
if (ff.isFormField()) {
String ds = ff.getString("UTF-8");//处理中文
System.err.println("说明是:" + ds);
} else {
String ss = ff.getName();
ss = ss.substring(ss.lastIndexOf("\\") + 1);//解析文件名
FileUtils.copyInputStreamToFile(
//直接使用commons.io.FileUtils
ff.getInputStream(),
new File(path + "/" + ss));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

1.3、FileItem接口
org.apache.commons.fileupload.disk.DiskFileItem实现了FileItem接口,用来封装单个表单字段元素的数据。通过调用FileItem 定义的方法可以获得相关表单字段元素的数据。我们不需要关心DiskFileItem的具体实现,在程序中可以采用FileItem接口类型来对DiskFileItem对象进行引用和访问。FileItem类还实现了Serializable接口,以支持序列化操作。

FileItem类常用的方法:

1. boolean isFormField()方法
isFormField方法用于判断FileItem类对象封装的数据是一个普通文本表单字段,还是一个文件表单字段,如果是普通表单字段则返回true,否则返回false。

2. String getName()方法

getName方法用于获得文件上传字段中的文件名,即表单字段元素描述头中的filename属性值,如“C:\Documents and Settings\All Users\Documents\My Pictures\示例图片\Sunset.jpg”。如果FileItem类对象对应的是普通表单字段,getName方法将返回null。即使用户没有通过网页表单中的文件字段传递任何
文件,但只要设置了文件表单字段的name属性,浏览器也会将文件字段的信息传递给服务器,只是文件名和文件内容部分都为空,但这个表单字段仍然对应一个FileItem对象,此时,getName方法返回结果为空字符串”“,读者在调用Apache文件上传组件时要注意考虑这个情况。
注意:上面的数据包是通过IE提交,所以是完整的路径和名称。如
C:\Documents and Settings\All Users\Documents\My Pictures\示例图片\Sunset.jpg。如果是其它浏览器,如火狐和Chromium,则仅仅是名字,没有路径,如Sunset.jpg。

3. String getFieldName()方法
getFieldName方法用于返回表单字段元素描述头的name属性值,也是表单标签name属性的值。例如“name=file1”中的“file1”。

4. void write(File file)方法
write方法用于将FileItem对象中保存的主体内容保存到某个指定的文件中。如果FileItem对象中的主体内容是保存在某个临时文件中,该方法顺利完成后,临时文件有可能会被清除。该方法也可将普通表单字段内容写入到一个文件中,但它主要用途是将上传的文件内容保存在本地文件系统中。

5. String getString()方法
getString方法用于将FileItem对象中保存的数据流内容以一个字符串返回,它有两个重载的定义形式:
public java.lang.String getString()
public java.lang.String getString(java.lang.String encoding) throws java.io.UnsupportedEncodingException
前者使用缺省的字符集编码将主体内容转换成字符串,后者使用参数指定的字符集编码将主体内容转换成字符串。如果在读取普通表单字段元素的内容时出现了中文乱码现象,请调用第二个getString方法,并为之传递正确的字符集编码名称。

6. String getContentType()方法
getContentType 方法用于获得上传文件的类型,即表单字段元素描述头属性“Content-Type”的值,如“image/jpeg”。如果FileItem类对象对应的是普通表单字段,该方法将返回null。

7. boolean isInMemory()方法
isInMemory方法用来判断FileItem对象封装的数据内容是存储在内存中,还是存储在临时文件中,如果存储在内存中则返回true,否则返回false。

8. void delete()方法
delete方法用来清空FileItem类对象中存放的主体内容,如果主体内容被保存在临时文件中,delete方法将删除该临时文件。尽管当FileItem对象被垃圾收集器收集时会自动清除临时文件,但及时调用delete方法可以更早的清除临时文件,释放系统存储资源。另外,当系统出现异常时,仍有可能造成有的临时文件被永久保存在了硬盘中。

9. InputStream getInputStream()方法
以流的形式返回上传文件的数据内容。

10. long getSize()方法
返回该上传文件的大小(以字节为单位)。

1.4、DiskFileItemFactory

此类将请求消息实体中的每一个项目封装成单独的DiskFileItem (FileItem接口的实现) 对象的任务由 org.apache.commons.fileupload.FileItemFactory 接口的默认实现 org.apache.commons.fileupload.disk.DiskFileItemFactory 来完成。当上传的文件项目比较小时,直接保存在内存中(速度比较快),比较大时,以临时文件的形式,保存在磁盘临时文件夹(虽然速度慢些,但是内存资源是有限的)。
属性:
1) public static final int DEFAULT_SIZE_THRESHOLD :
将文件保存在内存还是磁盘临时文件夹的默认临界值,值为10240,即10kb。

2) private File repository:
用于配置在创建文件项目时,当文件项目大于临界值时使用的临时文件夹,默认采用系统默认的临时文件路径,可以通过系统属性 java.io.tmpdir
获取。代码:System.getProperty(“java.io.tmpdir”);

3) private int sizeThreshold:
用于保存将文件保存在内存还是磁盘临时文件夹的临界值。

构造方法:

1) public DiskFileItemFactory():
采用默认临界值和系统临时文件夹构造文件项工厂对象。
2) public DiskFileItemFactory(int sizeThreshold,File repository):
采用参数指定临界值和系统临时文件夹构造文件项工厂对象。

其他方法:
1、FileItem createItem() 方法
根据DiskFileItemFactory相关配置将每一个请求消息实体项目创建 成DiskFileItem 实例,并返回。该方法从来不需要我们亲自调用,FileUpload组件在解析请求时内部使用。

2、void setSizeThreshold(int sizeThreshold)
Apache文件上传组件在解析上传数据中的每个字段内容时,需要临时保存解析出的数据,以便在后面进行数据的进一步处理(保存在磁盘特定位置或插入数据库)。因为Java虚拟机默认可以使用的内存空间是有限的,超出限制时将会抛出“java.lang.OutOfMemoryError”错误。如果上传的文件
很大,例如800M的文件,在内存中将无法临时保存该文件内容,Apache文件上传组件转而采用临时文件来保存这些数据;但如果上传的文件很小,例如600个字节的文件,显然将其直接保存在内存中性能会更加好些。

3、setSizeThreshold
方法用于设置是否将上传文件已临时文件的形式保存在磁盘的临界值(以字节为单位的int值),如果从没有调用该方法设置此临界值,将会采用系统默认值10KB。对应的getSizeThreshold() 方法用来获取此临界值。

4、void setRepository(File repository)
setRepositoryPath方法用于设置当上传文件尺寸大于setSizeThreshold方法设置的临界值时,将文件以临时文件形式保存在磁盘上的存放目录。有一个对应的获得临时文件夹的 File getRespository() 方法。
注意:当从没有调用此方法设置临时文件存储目录时,默认采用系统默认的临时文件路径,可以通过系统属性 java.io.tmpdir 获取。
如下代码:
System.getProperty(“java.io.tmpdir”);
Tomcat系统默认临时目录为“

package cn.itcast.servlet;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Scanner;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
/**
 * FileItemStream示例
 * @author <a href="mailto:wj@itcast.cn">王健</a>
 * @version 1.0 2012-3-15
 */
public class Upload3Servlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
long start = System.currentTimeMillis();
String path = getServletContext().getRealPath("/imgs");
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setSizeThreshold(1024 * 8);// 设置8k的缓存空间
factory.setRepository(new File("d:/a"));
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("UTF-8");// 设置文件名处理中文编码
try {
FileItemIterator fii = upload.getItemIterator(request);// 使用遍历类
while (fii.hasNext()) {
FileItemStream fis = fii.next();
if (fis.isFormField()) {//FileItemStream同样使用OpenStream获取普通表单的值
InputStreamReader in = new InputStreamReader(fis.openStream(),"UTF-8");
Scanner sc = new Scanner(in);
StringBuffer sb = new StringBuffer();
if(sc.hasNextLine()){
sb.append(sc.nextLine());
}
System.err.println("Desc:"+sb.toString());
} else {
String fileName = fis.getName();
fileName = fileName
.substring(fileName.lastIndexOf("\\") + 1);
System.err.println("文件名为:" + fileName);
InputStream in = fis.openStream();
FileUtils.copyInputStreamToFile(in, new File(path+"/"+fileName));
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.err.println("用时:"+(end-start));
}
}

1.7、FileCleanerCleanup清理资源

只适用于你使用 DiskFileItem 的情况.换句话说,就是在你处理上传的数据之前它们被存放在临时文件中。
这些临时文件在不再被使用的时候(如果相应的java.io.File是可回收的则更好)会自动被删除.这会被org.apache.commons.io.FileCleaningTracker的一个实例启动的一个收割线程默默执行。

 你的web应用应该使用org.apache.commons.fileupload.FileCleanerCleanup的一个实例.那很简单,你只要把它加到你的 web.xml 中:

<listener>
  <listener-class>org.apache.commons.fileupload.servlet.FileCleanerCleanup</listener-class>
  </listener>

然后,在创建了DiskFileItemFactory以后,设置资源回收:
DiskFileItemFactory f = new DiskFileItemFactory();//声明临时文件对象
f.setFileCleaningTracker(FileCleanerCleanup.getFileCleaningTracker(this.getServletContext()));
f.setSizeThreshold(1024*8);
//设置在内存中最多可以放多少个字节,如果超出这个字节,保存到临文件中去
f.setRepository(new File(“d:/a”));
//设置临时目录

注意:必须要正常关闭Tomcat服务器。因为此线程在tomcat终止时会调用清空临时文件的代码。
正常关闭,是指执行CATALINA_HOME\bin\shutdown.bat文件。

1.8、进度ProgressListener
这个进度条比较合适于在后台监控进度,如果在作上传进度,还是使用ajax更加合适:
示例代码:

upload.setProgressListener(new ProgressListener() {
double dd = 0;
long len = 0;
//参数1:已经上传完成的数量
//参数2:总长度
//参数3:第几个元素从1开始。0为没有
public void update(long pBytesRead, long pContentLength, int pItems) {
double persent = pBytesRead*100/pContentLength;
if(dd!=persent){
System.err.println(dd+"%");
dd=persent;
}else if(persent==100){
System.err.println("100%");
}
}
});
<script type="text/javascript"> $(function () { $('pre.prettyprint code').each(function () { var lines = $(this).text().split('\n').length; var $numbering = $('<ul/>').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($('<li/>').text(i)); }; $numbering.fadeIn(1700); }); }); </script>
分享到:
评论

相关推荐

    Apache FileUpload文件上传组件API解析

    尽管 Apache 推荐使用 `ServletFileUpload` 类,但两者方法相似,以下介绍 `DiskFileUpload` 类中的关键方法: 1. **`setSizeMax` 方法**:此方法用于设定请求消息实体的最大允许大小,以防客户端上传过大的文件...

    apache fileupload 文件上传实例

    本实例将深入讲解如何使用Apache FileUpload进行文件上传操作。 1. **Apache FileUpload简介** Apache Commons FileUpload是Apache软件基金会的一个子项目,它提供了处理HTTP请求中multipart/form-data类型的工具...

    Apache Commons FileUpload jar

    Apache Commons FileUpload jar Apache Commons FileUpload jar Apache Commons FileUpload jar

    Apache Commons FileUpload 1.3.2 released

    The Apache Commons FileUpload component provides a simple yet flexible means of adding support for multipart file upload functionality to servlets and web applications. Changes in this release are: o...

    jQuery Uploadify + Apache Fileupload异步上传文件示例

    本示例探讨了如何结合jQuery Uploadify插件与Apache Fileupload库来实现这一功能,主要面向Java后端开发。这里我们将深入讲解这两个组件的工作原理、集成过程以及关键知识点。 1. jQuery Uploadify 插件: jQuery ...

    apache fileupload处理文件上传(流式和非流式)

    Apache FileUpload是一个强大的Java库,专门用于处理HTTP协议中的文件上传功能。在Web应用中,尤其是在用户需要上传大文件时,FileUpload库提供了一种高效且灵活的方式来管理这些操作。它支持两种主要的工作模式:...

    基于apache commons.fileupload的文件上传组件,改进了上传速度

    apache commons.fileupload上传组件在上传文件时,在调用parseRequest方法时,先将输入流上传到服务器临时目录,在之后的文件处理过程中,再将临时目录下保存的文件复制到指定的目录,多了一道转储步骤。本实现抽取...

    基于apache commons.fileupload的文件上传组件

    以下是一些关于Apache Commons FileUpload的关键知识点: 1. **多部分解析**:FileUpload库的核心功能是解析HTTP请求中的多部分数据。HTTP规范规定,文件上传通常通过“multipart/form-data”编码方式进行,...

    Apache Commons fileUpload实现文件上传

    1. 添加依赖:在项目中引入Apache Commons IO和FileUpload的JAR文件,或者在Maven或Gradle项目中添加对应的依赖。 2. 创建Servlet或控制器:设置请求的解析器,例如在Servlet中使用`ServletFileUpload`类。 3. ...

    JSP上传文件Servlet(Apache fileUpload)同时text文本

    本教程将详细介绍如何使用JSP和Servlet结合Apache Commons FileUpload库实现文件上传,并同时处理text文本。 首先,我们需要在项目中引入Apache Commons FileUpload库。通常,这可以通过在pom.xml文件中添加依赖来...

    apache的fileupload详解

    这篇博客文章深入讲解了如何使用Apache Commons FileUpload库来处理文件上传请求,以及相关的源码分析。 一、Apache Commons FileUpload简介 Apache Commons FileUpload是Apache软件基金会的一个开源项目,它提供了...

    用apache fileupload 实现基于http协议的断点续传,断点上载,含测试用的客户端

    Apache FileUpload是一个强大的Java库,专门用于处理HTTP请求中的多部分数据,比如文件上传。在传统的HTTP上传过程中,如果文件较大,用户可能会因为网络中断等原因导致上传失败,这时断点续传功能就显得尤为重要。...

    org.apache.commons.fileupload.DiskFileUpload使用上

    `org.apache.commons.fileupload.DiskFileUpload` 是 Apache Commons FileUpload 模块中的一个类,主要用于处理 HTTP 请求中的文件上传。这个类实现了基于磁盘的文件上传存储策略,当上传文件大小超过内存阈值时,它...

    利用org.apache.commons.fileupload上传多个文件

    在使用 Apache Commons FileUpload 进行文件上传之前,你需要确保以下组件已经准备就绪: 1. **引入依赖**:首先,你需要下载并添加 `org.apache.commons.io` 和 `log4j` 的 JAR 包到你的项目类路径中。在本例中,`...

    org.apache.commons.fileupload 文件上传至数据库

    标题“org.apache.commons.fileupload 文件上传至数据库”指的是使用Apache Commons FileUpload库将用户上传的文件存储到数据库中的技术。Apache Commons FileUpload是Apache软件基金会的一个开源项目,它提供了一个...

    commons-fileupload-1.3.3.zip

    Apache Struts2 Commons FileUpload反序列化远程代码执行漏洞安全公告 安全公告编号:CNTA-2018-0029 2018年11月7日,国家信息安全漏洞共享平台(CNVD)收录了Apache Struts2 Commons FileUpload反序列化远程代码...

    commons-fileupload-1.4-bin.zip

    《Apache Commons FileUpload组件详解》 Apache Commons FileUpload是一个用于处理HTTP请求中多部分数据的Java库,尤其在上传文件时极为有用。标题中的"commons-fileupload-1.4-bin.zip"表明这是一个包含Apache ...

    apache commons fileupload api_zh

    apache commons fileupload api_zh

Global site tag (gtag.js) - Google Analytics