commom fileupload简介

一.概述

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

1. 默认的FileItemFactory实现,根据阈值判断是将上传的文件保存在内存还是缓存到本地磁盘
2. DiskFileItemFactory详见:DiskFileItemFactory简介
3. DiskFileFileItemFactory实例化
//为基于磁盘的文件项创建工厂
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

解析完成后,您将有一个需要处理的文件 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
对于常规表单字段,您很可能只对该item的名称及其String值感兴趣。正如你所期望的,访问这些是非常简单的。
// 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。换句话说,只适用于上传文件在处理它们之前被写入临时文件。

如果不再使用这些临时文件,则会自动删除这些临时文件(更准确地说,如果相应的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
FileCleanerCleanup提供了一个org.apache.commons.io.FileCleaningTracker的实例 。创建org.apache.commons.fileupload.disk.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 禁用临时文件的清理
要禁用对临时文件的跟踪,可以将FileCleaningTracker设置 为null。因此,创建的文件将不再被跟踪。特别是,它们将不再被自动删除。
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);
如果想实现自己的第一个进度监听器,就像上面那样。
它有一个缺陷:进度监听器被调用得很频繁。 
根据servlet引擎和其他环境工厂,进度监听器可能会被任何网络包调用! 换句话说,您的进度侦听器可能会成为性能问题! 典型的解决方案可能是减少进度侦听器的活动。 
例如,如果上传了兆字节数,才发送一条消息
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值