前言

关于JSP 文件上传的基础和原理在系列一中有介绍到。 这里介绍一个很流行的组件commons fileupload,用来加速文件上传的开发。

官方的介绍是:  让添加强壮,高性能的文件到你的servlet和Web应用程序变得容易。

官方项目地址:

http://commons.apache.org/proper/commons-fileupload/

FileUpload分析request 里的数据,  生成一些独立的上传items. 每一个item都继承自 FileItem 这个接口。

下载导入

1. 可以到 http://commons.apache.org/proper/commons-fileupload/download_fileupload.cgi 这个地址下载最新的版本。

2. 另外还需要下载 commons-io的 jar 包,下载地址:

http://commons.apache.org/proper/commons-fileupload/dependencies.html

在servlet 和portlet中都可以使用FileUpload, 以下以servlet的使用来介绍

分析请求(request)

首先,需要判断request 是否是文件上传的request.

系列一也有提,文件上传的form 必须设置成如下:

<form method="POST" enctype="multipart/form-data" action="fileUploadServlet">

这里有提供一个方法判断request 是否是正确的类型

// Check that we have a file upload request
boolean isMultipart = ServletFileUpload.isMultipartContent(request);

例如这里, 如果form 中移除enctype="multipart/form-data", 返回值就是false 了。

最简单的状况

最简单的使用场景如下:

1. 如果上传的文件足够小的话应该保存在内存中

2. 大的文件应该写到临时文件中

3. 超大的文件上传请求应该不被允许

4. 内存中的文件最大值,允许上传的文件最大尺寸和临时文件目录的接收默认的设置。

看个实例:

// Create a factory for disk-based file items
FileItemFactory factory = new DiskFileItemFactory();// Configure a repository (to ensure a secure temp location is used)
ServletContext servletContext = this.getServletConfig().getServletContext();
File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
factory.setRepository(repository);// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);// Parse the request
List<FileItem> items = upload.parseRequest(request);

更多的控制

也可以进行更多的设置, 看例子

// Create a factory for disk-based file items
DiskFileItemFactory factory = new DiskFileItemFactory();// Set factory constraints
factory.setSizeThreshold(yourMaxMemorySize);
factory.setRepository(yourTempDirectory);// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);// Set overall request size constraint
upload.setSizeMax(yourMaxRequestSize);// Parse the request
List<FileItem> items = upload.parseRequest(request);

这里设置了最大内存大小,临时文件路径和文件最大值。

设置方式也可以这样:

DiskFileItemFactory factory = new DiskFileItemFactory(yourMaxMemorySize, yourTempDirectory);

处理上传的item

需要再提一下的是: FileUpload 不仅会把一个file 的input 放入一个 FileItem, 一般的Form text input 也会放入一个FileItem.

所以在分析完之后接下来就是如何处理这些FileItem 了。

// Process the uploaded items
Iterator<FileItem> iter = items.iterator();
while (iter.hasNext()) {FileItem item = iter.next();if (item.isFormField()) {processFormField(item);} else {processUploadedFile(item);}
}

对于一般的form field 来说(text input), 无非就是取它的name 和value  了。

// Process a regular form field
if (item.isFormField()) {String name = item.getFieldName();String value = item.getString();...
}

对于文件类型的话, 可以

// 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();...
}

看是否需要写入到某个文件中:

// Process a file upload
if (writeToFile) {File uploadedFile = new File(...);item.write(uploadedFile);
} else {InputStream uploadedStream = item.getInputStream();...uploadedStream.close();
}

得到文件

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

资源清除

如果使用DiskFileItem, 或者说在处理上传文件之前写入临时文件的话,就要考虑资源清除了。

临时文件不再使用的话,是会自动被删除的。org.apache.commons.io.FileCleaner 这个类会启动一个回收线程。

如果不再需要这个回收线程的话, 可以停止它。 方法是在xml 中加入:

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


创建一个 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;
}

如果不想删除临时文件的话, 设置 FileCleaningTracker为null 就可以了。 因此,创建的文件将不再被跟踪。特别是,它们将不再被自动删除。

与病毒扫描软件的问题

病毒扫描软件可能会导致FileUpload 的一些异常状况。

解决方式就是让扫描软件不要监视某些特定的目录。

查看上传进度

//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);

或者

//Create a progress listener
ProgressListener 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.");}}
};

Streaming API

上面提到的API (传统API) 是在使用前完全把Item  读到某个地方(内存或是文件),使用Streaming 的话,可以逐步的读取, 性能和内存使用都会大大提升。

// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload();// Parse the request
FileItemIterator iter = upload.getItemIterator(request);
while (iter.hasNext()) {FileItemStream item = iter.next();String name = item.getFieldName();InputStream stream = item.openStream();if (item.isFormField()) {System.out.println("Form field " + name + " with value "+ Streams.asString(stream) + " detected.");} else {System.out.println("File field " + name + " with file name "+ item.getName() + " detected.");// Process the input stream...}
}

JSP 文件上传下载系列之二[Commons fileUpload]相关推荐

  1. JSP 文件上传下载系列之一[基本方式上传文件]

    前言 在jsp的web项目中,很有可能会使用文件上传的功能. 把一个本地的文件上传到web 服务器的某个路径下. 对于java 来说, 实现这样功能的开源组件有很多, 比如较常用的commons-fi ...

  2. 直链文件上传下载网站分享(二)

    直链文件上传下载网站分享(一) 直链文件上传下载网站分享(二) 八.GM帮登陆器列表空间 九.墨涩网外链系统 十.树洞外链 十一.豆子外链 十二.凡人外链 十三.图钉外链 十四.小西外链 直链文件上传 ...

  3. 文件上传下载系列——如何实现文件秒传

    文章目录

  4. 狂神说SpringMVC08:拦截器+文件上传下载

    狂神说SpringBoot系列连载课程,通俗易懂,基于SpringBoot2.2.5版本,欢迎各位狂粉转发关注学习.未经作者授权,禁止转载 这是SpringMVC视频同步的最后一章:拦截器以及文件的上 ...

  5. 【SpringMVC笔记】拦截器 + 文件上传下载

    拦截器 + 文件上传下载 拦截器(interceptor) 自定义拦截器 验证用户是否登录 (认证用户) 没有拦截器 配置拦截器 文件的上传 文件输出流进行文件上传 file.Transto 进行文件 ...

  6. 关于SpringMVC框架实现简单的文件上传下载(ssm)

    关于ssm框架整合文件的上传和下载. 首先来看单个附件的上传和下载: 1.首先创建一个用来测试的jsp文件上传下载的页面  代码如下 <%@ page language="java&q ...

  7. [C# 网络编程系列]专题十一:实现一个基于FTP协议的程序——文件上传下载器...

    引言: 在这个专题将为大家揭开下FTP这个协议的面纱,其实学习知识和生活中的例子都是很相通的,就拿这个专题来说,要了解FTP协议然后根据FTP协议实现一个文件下载器,就和和追MM是差不多的过程的,相信 ...

  8. JSP基础:(7)jsp分页与文件上传下载

    目录 1 jsp分页 1.1 定义 1.2 Servlet控制器方法 2 文件上传下载 2.1 定义 2.2 SmartUpload 2.2.1 介绍 2.2.2 SmartUpload组件-Requ ...

  9. 基于华为云obs实现文件上传下载(技术栈mysql+springboot+Maven+jsp+java)的技术分享

    基于华为云obs实现文件上传下载(技术栈mysql+springboot+jsp+java)的技术分享 obs实现文件上传下载 前言 一.OBS是什么? 二.使用步骤 1.1 前期准备 2 工具的内容 ...

最新文章

  1. maven打包记录1
  2. Docker之几种storage-driver比较
  3. Spring框架—IoC容器
  4. 07_QueueWithTwoStacks
  5. 【渝粤教育】国家开放大学2018年秋季 1007t公司财务 参考试题
  6. 高级I/O(七)--readv和writev函数
  7. Unity5.3官方VR教程重磅登场-系列7 优化VR体验
  8. 毕设题目:Matlab图像去噪
  9. 模型参考自适应控制器(MRAC)系列: 2.提升瞬态性能
  10. Linux使用lrzsz快速上传和下载
  11. Java IO流关闭顺序
  12. 量子计算机能做到0延迟吗,延迟选择量子擦除实验
  13. 傅里叶变换和正弦函数和欧拉公式
  14. 抽象层 abstraction layer
  15. 论文阅读Reasoning with Latent Structure Refinement for Document-Level Relation Extraction
  16. java如何画五角星_Java——绘制五角星
  17. The bean ‘Xxx‘ could not be injected as a ‘Xxx‘ because it is a JDK dynamic proxy that implements:x
  18. Python知识拓展
  19. 7-20 电话聊天狂人(25 分)(Hash模板)
  20. 计算机网络用户名及密码如何查询,用wifi连接电脑的怎么查看宽带账号密码

热门文章

  1. 视图自己定义旋转动画 相似百度音乐
  2. 生命太短暂,我没时间讨厌你
  3. Hiberbate中的一对多关联查询
  4. DeepFaceLab报错,CUDA driver is insufficient 解决方法!
  5. 【干货】常见的40个知识模型:学习力、思考力、创造力、共情力......
  6. 【图解+全文】工信部关于印发“十四五”大数据产业发展规划的通知
  7. 【报告分享】Facebook IQ 2020年热门话题和趋势报告.pdf(附下载链接)
  8. 【报告分享】2019区块链赋能新型智慧城市白皮书.pdf(附204页电子书下载链接)
  9. 2015-2020年各类国际会议与期刊基于图像的三维对象重建论文综述(8)——Comparison
  10. ole db 访问接口 sqlncli 无法启动分布式事务_分布式事务,看这篇就够了