一.概述
Commons FileUpload软件包可以轻松地为您的servlet和Web应用程序添加强大的高性能文件上传功能。
FileUpload解析符合RFC 1867“HTML格式的文件上传”的HTTP请求 。也就是说,如果使用POST方法提交HTTP请求,并且内容类型为“multipart / form-data”,则FileUpload可以解析该请求,并以调用者轻松使用的方式使结果可用。
从1.3版开始,FileUpload处理 RFC 2047编码的头值。
二.表单上传文件格式
向服务器发送多部分/表单数据请求的最简单的方法是通过Web表单,即
<form method="POST" enctype="multipart/form-data" action="">
上传文件: <input type="file" name="upfile"><br/>
上传文件备注: <input type="text" name="note"><br/>
<br/>
<input type="submit" value="Press"> 上传
</form>
三.DiskFileItemFactory
//为基于磁盘的文件项创建工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
// 缓存上传文件的本地文件夹路径
ServletContext servletContext = this.getServletConfig().getServletContext();
File repository =(File)servletContext.getAttribute(“javax.servlet.context.tempdir”);
factory.setRepository(repository );
四.ServletFileUpload
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
// Parse the request
List<FileItem> items = upload.parseRequest(request);
五.处理解析出的item
// Process the uploaded items
Iterator<FileItem> iter = items.iterator();
while (iter.hasNext()) {
FileItem item = iter.next();
if (item.isFormField()) {// item是表单字段
processFormField(item);
} else {// item是上传文件
processUploadedFile(item);
}
}
5.1 表单字段item
// Process a regular form field
if (item.isFormField()) {// item是表单字段
String name = item.getFieldName();
String value = item.getString();
...
}
5.2 上传文件item
// Process a file upload
if (!item.isFormField()) {
String fieldName = item.getFieldName();
String fileName = item.getName();
String contentType = item.getContentType();
boolean isInMemory = item.isInMemory();
long sizeInBytes = item.getSize();
...
}
六.资源清理Resource cleanup
如果不再使用这些临时文件,则会自动删除这些临时文件(更准确地说,如果相应的DiskFileItem实例 被垃圾回收,则可以通过org.apache.commons.io.FileCleanerTracker 类静默地创建这个临时文件,该类可以启动还原线程。
如果不再需要,这个收货人线程应该停止。在servlet环境中,这是通过使用一个名为FileCleanerCleanup的特殊servlet上下文监听器 完成的。为此,在web.xml中添加如下所示的部分:
<web-app>
...
<listener>
<listener-class>
org.apache.commons.fileupload.servlet.FileCleanerCleanup
</listener-class>
</listener>
...
</web-app>
6.1 创建一个DiskFileItemFactory
public static DiskFileItemFactory newDiskFileItemFactory(ServletContext context, File repository) {
FileCleaningTracker fileCleaningTracker = FileCleanerCleanup.getFileCleaningTracker(context);
DiskFileItemFactory factory = new DiskFileItemFactory(DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD, repository);
factory.setFileCleaningTracker(fileCleaningTracker);
return factory;
}
6.2 禁用临时文件的清理
6.3 与病毒扫描器的互动
在与Web容器相同的系统上运行的病毒扫描程序可能会对使用FileUpload的应用程序造成一些意外的行为。本节介绍您可能遇到的一些行为,并提供了一些如何处理它们的想法。
FileUpload的默认实现将导致高于一定大小阈值的上传项目写入磁盘。一旦这样的文件关闭,系统上的任何病毒扫描程序将被唤醒并检查它,并可能隔离文件 - 也就是将其移动到不会导致问题的特殊位置。这当然对应用程序开发人员来说将是一个惊喜,因为上传的文件将不再可用于处理。另一方面,同一阈值以下的上传项目将被保存在内存中,因此病毒扫描程序将不会被看到。这允许以某种形式保留病毒的可能性(尽管如果将其写入磁盘,病毒扫描程序将定位并检查它)。
一个常用的解决方案是在系统上放置一个目录,其中将放置所有上传的文件,并配置病毒扫描程序以忽略该目录。这样可以确保文件不会被从应用程序中删除,但是后来将病毒扫描负责给应用程序开发人员。然后可以通过外部进程扫描上传的文件以进行病毒扫描,这可能会将干净或清除的文件移动到“已批准”位置,或者通过将病毒扫描程序集成到应用程序本身内。配置外部进程或将病毒扫描集成到应用程序中的细节不在本文档的范围之内。
七.看进度
如果您希望文件上传真的很大,那么向用户报告已经收到了多少。即使HTML页面允许通过返回多部分/替换响应或类似的方式来实现进度条。
观看上传进度可以通过提供进度侦听器来完成:
//Create a progress listener
ProgressListener progressListener = new ProgressListener(){
public void update(long pBytesRead, long pContentLength, int pItems) {
System.out.println("We are currently reading item " + pItems);
if (pContentLength == -1) {
System.out.println("So far, " + pBytesRead + " bytes have been read.");
} else {
System.out.println("So far, " + pBytesRead + " of " + pContentLength + " bytes have been read.");
}
}
};
upload.setProgressListener(progressListener);
如果想实现自己的第一个进度监听器,就像上面那样。