JSP 文件上传下载系列之二[Commons fileUpload]
前言
关于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 =newDiskFileItemFactory(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 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 =newFile(...);
- item.write(uploadedFile);}else{
- InputStream uploadedStream = item.getInputStream();
- ...
- uploadedStream.close();}
得到文件
- // Process a file upload in memorybyte[] 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则需要这个实例。像
- publicstaticDiskFileItemFactory newDiskFileItemFactory(ServletContext context,
- File repository){
- FileCleaningTracker fileCleaningTracker
- =FileCleanerCleanup.getFileCleaningTracker(context);
- DiskFileItemFactory factory
- =newDiskFileItemFactory(DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD,
- repository);
- factory.setFileCleaningTracker(fileCleaningTracker);
- return factory;}
如果不想删除临时文件的话, 设置 FileCleaningTracker为null 就可以了。 因此,创建的文件将不再被跟踪。特别是,它们将不再被自动删除。
与病毒扫描软件的问题
病毒扫描软件可能会导致FileUpload 的一些异常状况。
解决方式就是让扫描软件不要监视某些特定的目录。
查看上传进度
- //Create a progress listenerProgressListener progressListener =newProgressListener(){
- publicvoid 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 =newProgressListener(){
- privatelong megaBytes =-1;
- publicvoid 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]的更多相关文章
- jsp文件上传下载组件
我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用. 首先我们需要了解的是上传文件三要素: 1.表单提交方式:post (get方式提交有大小 ...
- SpringMVC 文件上传下载
目录 文件上传 MultipartFile对象 文件下载 上传下载示例 pom.xml增加 创建uploadForm.jsp 创建uploadForm2.jsp 创建userInfo.jsp spri ...
- 基于struts2--实现文件上传下载
1. 文件的上传: 1). 表单需要注意的 3 点 ①. method="post" ②. enctype="mulitipart/form-data" ...
- JAVA Web 之 struts2文件上传下载演示(二)(转)
JAVA Web 之 struts2文件上传下载演示(二) 一.文件上传演示 详细查看本人的另一篇博客 http://titanseason.iteye.com/blog/1489397 二.文件下载 ...
- 使用Typescript重构axios(二十五)——文件上传下载进度监控
0. 系列文章 1.使用Typescript重构axios(一)--写在最前面 2.使用Typescript重构axios(二)--项目起手,跑通流程 3.使用Typescript重构axios(三) ...
- SpringBoot入门一:基础知识(环境搭建、注解说明、创建对象方法、注入方式、集成jsp/Thymeleaf、logback日志、全局热部署、文件上传/下载、拦截器、自动配置原理等)
SpringBoot设计目的是用来简化Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过这种方式,SpringBoot致力于在蓬勃发 ...
- salesforce 零基础学习(四十二)简单文件上传下载
项目中,常常需要用到文件的上传和下载,上传和下载功能实际上是对Document对象进行insert和查询操作.本篇演示简单的文件上传和下载,理论上文件上传后应该将ID作为操作表的字段存储,这里只演示文 ...
- jsp+servlet实现文件上传下载
相关素材下载 01.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" ...
- SpringMVC文件上传下载
在Spring MVC的基础框架搭建起来后,我们测试了spring mvc中的返回值类型,如果你还没有搭建好springmvc的架构请参考博文->http://www.cnblogs.com/q ...
随机推荐
- 闲来瞎扯 -- 在vs2008下编写linux程序
虽说vim很强大,但是个人感觉器代码提示功能不如visual assist来的强大.如何使用visual assist来实现代码的提示功能呢? 首先说明我的环境 : 宿主机是xp(O(∩_∩)O~还是 ...
- linux的NetworkManager服务(转)
在开启NetworkManager服务的情况下,在终端下敲“service network restart”命令: 正在关闭接口 eth0: 设备状态:3 (断开连接) [确定] 正在关闭接口 eth ...
- cf459C Pashmak and Buses
C. Pashmak and Buses time limit per test 1 second memory limit per test 256 megabytes input standard ...
- 如何将Oracle安装为Linux服务
方法一:使用oracle自带的启动和关闭脚本 1. oracle用户修改/etc/oratab 文件: $ vi /etc/oratab orcl:/oracle/app/product/10.2.0 ...
- poj 1328 Radar Installation_贪心
翻出一年多前的代码看,发现以前的代码风格很糟糕 题意:给你n个点 m为圆的半径,问需要多少个圆能把全部点圈到 #include <iostream> #include <algori ...
- PHP - Mysql数据库备份类
使用方法: require_once("backdata.class.php"); $link =@mysql_connect("localhost",&quo ...
- malloc用法
malloc用法三部曲:(#include<stdlib.h>下的库函数) 1.malloc eg.ps=(char*)malloc(sizeof(char)*20)的意思是,动态分配空间 ...
- Mysql数据库启动
1.改变数据库的访问ip: vim /etc/mysql/my.cnf 找到下面选项: bind-address = 192.168.1.128 修改即可. 2.mysql启动命 ...
- H264 编码详解
H264 编码详解(收集转载) (1) x264_param_default( x264_param_t *param ) 作用: 对编码器进行参数设定 cqm:量化表相关信息 csp: ...
- Vbox 未指定XXX网络名称 找不到网卡问题
链接方式不止Host-Only 我一般选桥连 选择 VBoxNetFltM.inf VBoxNetFltM.inf VirtualBox的桥接网络驱动程序的INF文件(Miniport:端口) VBo ...