Apache Commons FileUpload

来源:互联网 发布:我是大主宰服务端源码 编辑:程序博客网 时间:2024/05/17 16:13

文件上传


Apache Commons FileUpload是用于解析上传文件的包。这里将其一些简单的特性和使用进行一个大概的介绍。

一.简介

用于解析上传的文件,"Form-based File Upload in HTML"。也就是说,如果使用POST方法提交HTTP请求,并且使用内容类型“multipart / form-data”,则FileUpload可以解析该请求。

二.简单使用

1.满足的条件

  • form表单使用POST请求,并且form表单的内容格式要定义成multipart/form-data格式
  • form表单内,要添加空间<input type="file" name="">或者其他的比如:Uploadify插件

     <form method="POST" enctype="multipart/form-data" action="fup.cgi">   File to upload: <input type="file" name="upfile"><br/>   Notes about the file: <input type="text" name="note"><br/>   <br/>   <input type="submit" value="Press"> to upload the file! </form>

    2.具体使用

  • 使用前判断是否有上传文件的请求
// Check that we have a file upload requestboolean isMultipart = ServletFileUpload.isMultipartContent(request);
  • 简单的例子
// Create a factory for disk-based file itemsDiskFileItemFactory factory = new DiskFileItemFactory();// Configure a repository (to ensure a secure temp location is used),默认会放在System.getProperty("java.io.tmpdir")ServletContext servletContext = this.getServletConfig().getServletContext();File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");factory.setRepository(repository);// Create a new file upload handlerServletFileUpload upload = new ServletFileUpload(factory);// Parse the requestList<FileItem> items = upload.parseRequest(request);
  • 加入一些控制的例子
// Create a factory for disk-based file itemsDiskFileItemFactory factory = new DiskFileItemFactory();// Set factory constraints//默认为10k,小于这个值的会放在内容中,否则放在设置的disk路径下factory.setSizeThreshold(yourMaxMemorySize);factory.setRepository(yourTempDirectory);// Create a new file upload handlerServletFileUpload upload = new ServletFileUpload(factory);// Set overall request size constraint,最大上传文件upload.setSizeMax(yourMaxRequestSize);// Parse the requestList<FileItem> items = upload.parseRequest(request);

也可以一并配置多个属性

// Create a factory for disk-based file itemsDiskFileItemFactory factory = new DiskFileItemFactory(yourMaxMemorySize, yourTempDirectory);
  • 获取上传的文件信息
// Process a file uploadif (!item.isFormField()) {    String fieldName = item.getFieldName();    String fileName = item.getName();    String contentType = item.getContentType();    boolean isInMemory = item.isInMemory();    long sizeInBytes = item.getSize();    ...}
  • 保存文件前获取文件的一些方式
// Process a file uploadif (writeToFile) {    File uploadedFile = new File(...);    item.write(uploadedFile);} else {    InputStream uploadedStream = item.getInputStream();    ...    uploadedStream.close();}

OR

// Process a file upload in memorybyte[] data = item.get();...

三.清理文件

仅仅适用于DiskFileItem,也就是说在上传前,文件被写入了临时文件,如果不再使用这些临时文件,则需要删除这些临时文件。DiskFileItemFactory有一个属性FileCleaningTracker,设置这个属性可以用来追踪删除临时文件。当这个临时文件不再被使用时将会被立即删除,更精确的说是这个文件对象被垃圾收集器回收时,FileCleaningTracker将启动收割者线程(reaper thread)自动删除这个临时文件。 为了确保这个
后台线程在它不再被需要时被停止,在 servlet 环境里,我们通过一个名叫 FileCleanerCleanup 的 s
ervlet 上下文监听器,在web应用关闭时调用FileCleaningTracker.exitWhenFinished()来终止收割机线
程。在servlet环境中,使用 FileCleanerCleanup,FileCleanerCleanup提供了FileCleaningTracker的一个实例,要让FileCleanerCleanup监听器工作,你需要在 web.xml 增加如下代码:。

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

在使用FileCleanerCleanup,应该像下面这样创建DiskFileItemFactory

public static DiskFileItemFactory newDiskFileItemFactory(ServletContext context,                                                         File repository) {    //FileCleaningTracker类,这个类用于跟踪要删除的文件    FileCleaningTracker fileCleaningTracker        = FileCleanerCleanup.getFileCleaningTracker(context);    DiskFileItemFactory factory        = new DiskFileItemFactory(DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD,                                  repository);    factory.setFileCleaningTracker(fileCleaningTracker);    return factory;}

四.上传进度

下面是一个创建进度监听的一个例子

//Create a progress listenerProgressListener 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);

但是这样会存在问题,有可能会被频繁的调用而造成性能问题。

//Create a progress listenerProgressListener progressListener = new ProgressListener(){   private long megaBytes = -1;   public void update(long pBytesRead, long pContentLength, int pItems) {       long mBytes = pBytesRead / 1000000;       if (megaBytes == mBytes) {           return;       }       megaBytes = mBytes;       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.");       }   }};

如果想在页面展示,可以自己实现一个ProgressListener接口,将进度的相关信息放在session中。通过ajax之类的进行调用。具体可以参照博客-- Common-FileUpload带进度条上传