diskfileupload(Java DiskFileUpload类使用实例)
一、java怎么用commons-fileupload实现上传文件
文件上传步骤:
1.导入jar包
common-fileupload.jar
common-io.jar
2.上传jsp页面编辑
<body>
<formaction="${pageContext.request.contextPath}/servlet/UploadHandleServlet"enctype="multipart/form-data"method="post">
上传用户:<inputtype="text"name="username"><br/>
上传文件1:<inputtype="file"name="file1"><br/>
上传文件2:<inputtype="file"name="file2"><br/>
<inputtype="submit"value="提交">
</form>
</body>
3.消息提示页面(成功or失败)
<body>
${message}
</body>
4.处理文件上传的servlet编写
importjava.io.File;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.InputStream;
importjava.util.List;
importjava.util.UUID;
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importorg.apache.commons.fileupload.FileItem;
importorg.apache.commons.fileupload.FileUploadBase;
importorg.apache.commons.fileupload.ProgressListener;
importorg.apache.commons.fileupload.disk.DiskFileItemFactory;
importorg.apache.commons.fileupload.servlet.ServletFileUpload;
publicclassUploadHandleServletextendsHttpServlet{
publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException{
//得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全
StringsavePath=this.getServletContext().getRealPath("/WEB-INF/upload");
//上传时生成的临时文件保存目录
StringtempPath=this.getServletContext().getRealPath("/WEB-INF/temp");
FiletmpFile=newFile(tempPath);
if(!tmpFile.exists()){
//创建临时目录
tmpFile.mkdir();
}
//消息提示
Stringmessage="";
try{
//使用Apache文件上传组件处理文件上传步骤:
//1、创建一个DiskFileItemFactory工厂
DiskFileItemFactoryfactory=newDiskFileItemFactory();
//设置工厂的缓冲区的大小,当上传的文件大小超过缓冲区的大小时,就会生成一个临时文件存放到指定的临时目录当中。
factory.setSizeThreshold(1024*100);//设置缓冲区的大小为100KB,如果不指定,那么缓冲区的大小默认是10KB
//设置上传时生成的临时文件的保存目录
factory.setRepository(tmpFile);
//2、创建一个文件上传解析器
ServletFileUploadupload=newServletFileUpload(factory);
//监听文件上传进度
upload.setProgressListener(newProgressListener(){
publicvoidupdate(longpBytesRead,longpContentLength,intarg2){
System.out.println("文件大小为:"+pContentLength+",当前已处理:"+pBytesRead);
/**
*文件大小为:14608,当前已处理:4096
文件大小为:14608,当前已处理:7367
文件大小为:14608,当前已处理:11419
文件大小为:14608,当前已处理:14608
*/
}
});
//解决上传文件名的中文乱码
upload.setHeaderEncoding("UTF-8");
//3、判断提交上来的数据是否是上传表单的数据
if(!ServletFileUpload.isMultipartContent(request)){
//按照传统方式获取数据
return;
}
//设置上传单个文件的大小的最大值,目前是设置为1024*1024字节,也就是1MB
upload.setFileSizeMax(1024*1024);
//设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为10MB
upload.setSizeMax(1024*1024*10);
//4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
List<FileItem>list=upload.parseRequest(request);
for(FileItemitem:list){
//如果fileitem中封装的是普通输入项的数据
if(item.isFormField()){
Stringname=item.getFieldName();
//解决普通输入项的数据的中文乱码问题
Stringvalue=item.getString("UTF-8");
//value=newString(value.getBytes("iso8859-1"),"UTF-8");
System.out.println(name+"="+value);
}else{//如果fileitem中封装的是上传文件
//得到上传的文件名称,
Stringfilename=item.getName();
System.out.println(filename);
if(filename==null||filename.trim().equals("")){
continue;
}
//注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt
//处理获取到的上传文件的文件名的路径部分,只保留文件名部分
filename=filename.substring(filename.lastIndexOf("\\")+1);
//得到上传文件的扩展名
StringfileExtName=filename.substring(filename.lastIndexOf(".")+1);
//如果需要限制上传的文件类型,那么可以通过文件的扩展名来判断上传的文件类型是否合法
System.out.println("上传的文件的扩展名是:"+fileExtName);
//获取item中的上传文件的输入流
InputStreamin=item.getInputStream();
//得到文件保存的名称
StringsaveFilename=makeFileName(filename);
//得到文件的保存目录
StringrealSavePath=makePath(saveFilename,savePath);
//创建一个文件输出流
FileOutputStreamout=newFileOutputStream(realSavePath+"\\"+saveFilename);
//创建一个缓冲区
bytebuffer[]=newbyte[1024];
//判断输入流中的数据是否已经读完的标识intlen=0;
//循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
while((len=in.read(buffer))>0){
//使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath+"\\"+filename)当中
out.write(buffer,0,len);
}
//关闭输入流
in.close();
//关闭输出流
out.close();//删除处理文件上传时生成的临时文件//item.delete();message="文件上传成功!";
}
}
}catch(FileUploadBase.FileSizeLimitExceededExceptione){
e.printStackTrace();
request.setAttribute("message","单个文件超出最大值!!!");
request.getRequestDispatcher("/message.jsp").forward(request,response);
return;
}catch(FileUploadBase.SizeLimitExceededExceptione){
e.printStackTrace();
request.setAttribute("message","上传文件的总的大小超出限制的最大值!!!");
request.getRequestDispatcher("/message.jsp").forward(request,response);
return;
}catch(Exceptione){
message="文件上传失败!";
e.printStackTrace();
}
request.setAttribute("message",message);
request.getRequestDispatcher("/message.jsp").forward(request,response);
}
privateStringmakeFileName(Stringfilename){//2.jpg
//为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名
returnUUID.randomUUID().toString()+"_"+filename;
}
privateStringmakePath(Stringfilename,StringsavePath){
//得到文件名的hashCode的值,得到的就是filename这个字符串对象在内存中的地址
inthashcode=filename.hashCode();
intdir1=hashcode&0xf;//0--15
intdir2=(hashcode&0xf0)>>4;//0-15
//构造新的保存目录
Stringdir=savePath+"\\"+dir1+"\\"+dir2;//upload\2\3upload\3\5
if(!file.exists()){
file.mkdirs();
}
returndir;
}
publicvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException{
doGet(request,response);
}
}
5.编写web.xml文件(servlet的映射配置)
<servlet>
<servlet-name>UploadHandleServlet</servlet-name>
<servlet-class>me.gacl.web.controller.UploadHandleServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UploadHandleServlet</servlet-name>
<url-pattern>/servlet/UploadHandleServlet</url-pattern>
</servlet-mapping>
注:网上看到的,出处找不到了,望见谅!!
二、Apache FileUpload文件上传组件API解析
Java Web开发人员可以使用Apache文件上传组件来接收浏览器上传的文件该组件由多个类共同组成但是对于使用该组件来编写文件上传功能的Java Web开发人员来说只需要了解和使用其中的三个类 DiskFileUpload FileItem和FileUploadException这三个类全部位于mons fileupload包中
DiskFileUpload类
DiskFileUpload类是Apache文件上传组件的核心类应用程序开发人员通过这个类来与Apache文件上传组件进行交互但现在Apache建议使用ServletFileUpload类两个类的方法类似下面介绍DiskFileUpload类中的几个常用的重要方法
.setSizeMax方法
setSizeMax方法用于设置请求消息实体内容的最大允许大小以防止客户端故意通过上传特大的文件来塞满服务器端的存储空间单位为字节其完整语法定义如下
public void setSizeMax(long sizeMax)
如果请求消息中的实体内容的大小超过了setSizeMax方法的设置值该方法将会抛出FileUploadException异常
.setSizeThreshold方法
Apache文件上传组件在解析和处理上传数据中的每个字段内容时需要临时保存解析出的数据因为Java虚拟机默认可以使用的内存空间是有限的(笔者测试不大于 M)超出限制时将会发生 java lang OutOfMemoryError错误如果上传的文件很大例如上传 M的文件在内存中将无法保存该文件内容 Apache文件上传组件将用临时文件来保存这些数据但如果上传的文件很小例如上传个字节的文件显然将其直接保存在内存中更加有效 setSizeThreshold方法用于设置是否使用临时文件保存解析出的数据的那个临界值该方法传入的参数的单位是字节其完整语法定义如下
public void setSizeThreshold(int sizeThreshold)
setRepositoryPath方法
setRepositoryPath方法用于设置setSizeThreshold方法中提到的临时文件的存放目录这里要求使用绝对路径其完整语法定义如下
public void setRepositoryPath(String repositoryPath)
如果不设置存放路径那么临时文件将被储存在 java io tmpdir这个JVM环境属性所指定的目录中 tomcat将这个属性设置为了<tomcat安装目录>/temp/目录
parseRequest方法
parseRequest方法是DiskFileUpload类的重要方法它是对HTTP请求消息进行解析的入口方法如果请求消息中的实体内容的类型不是 multipart/form data该方法将抛出FileUploadException异常 parseRequest方法解析出FORM表单中的每个字段的数据并将它们分别包装成独立的FileItem对象然后将这些FileItem对象加入进一个List类型的集合对象中返回 parseRequest方法的完整语法定义如下
public List parseRequest(HttpServletRequest req)
parseRequest方法还有一个重载方法该方法集中处理上述所有方法的功能其完整语法定义如下
parseRequest(HttpServletRequest req int sizeThreshold long sizeMax
String path)
这两个parseRequest方法都会抛出FileUploadException异常
isMultipartContent方法
isMultipartContent方法方法用于判断请求消息中的内容是否是 multipart/form data类型是则返回true否则返回false isMultipartContent方法是一个静态方法不用创建DiskFileUpload类的实例对象即可被调用其完整语法定义如下
public static final boolean isMultipartContent(HttpServletRequest req)
setHeaderEncoding方法
由于浏览器在提交FORM表单时会将普通表单中填写的文本内容传递给服务器对于文件上传字段除了传递原始的文件内容外还要传递其文件路径名等信息如后面的图所示不管FORM表单采用的是 application/x form urlencoded编码还是 multipart/form data编码它们仅仅是将各个FORM表单字段元素内容组织到一起的一种格式而这些内容又是由某种字符集编码来表示的关于浏览器采用何种字符集来编码FORM表单字段中的内容请参看笔者编著的《深入体验java Web开发内幕——核心基础》一书中的第的讲解 multipart/form data类型的表单为表单字段内容选择字符集编码的原理和方式与 application/x form urlencoded类型的表单是相同的 FORM表单中填写的文本内容和文件上传字段中的文件路径名在内存中就是它们的某种字符集编码的字节数组形式 Apache文件上传组件在读取这些内容时必须知道它们所采用的字符集编码才能将它们转换成正确的字符文本返回
对于浏览器上传给WEB服务器的各个表单字段的描述头内容 Apache文件上传组件都需要将它们转换成字符串形式返回 setHeaderEncoding方法用于设置转换时所使用的字符集编码其原理与笔者编著的《深入体验java Web开发内幕——核心基础》一书中的第节讲解的ServletRequest setCharacterEncoding方法相同 setHeaderEncoding方法的完整语法定义如下
public void setHeaderEncoding(String encoding)
其中 encoding参数用于指定将各个表单字段的描述头内容转换成字符串时所使用的字符集编码
注意如果读者在使用Apache文件上传组件时遇到了中文字符的乱码问题一般都是没有正确调用setHeaderEncoding方法的原因
FileItem类
FileItem类用来封装单个表单字段元素的数据一个表单字段元素对应一个FileItem对象通过调用FileItem对象的方法可以获得相关表单字段元素的数据 FileItem是一个接口在应用程序中使用的实际上是该接口一个实现类该实现类的名称并不重要程序可以采用FileItem接口类型来对它进行引用和访问为了便于讲解这里将FileItem实现类称之为FileItem类 FileItem类还实现了Serializable接口以支持序列化操作
对于 multipart/form data类型的FORM表单浏览器上传的实体内容中的每个表单字段元素的数据之间用字段分隔界线进行分割两个分隔界线间的内容称为一个分区每个分区中的内容可以被看作两部分一部分是对表单字段元素进行描述的描述头另外一部是表单字段元素的主体内容如图所示
图
主体部分有两种可能性要么是用户填写的表单内容要么是文件内容 FileItem类对象实际上就是对图中的一个分区的数据进行封装的对象它内部用了两个成员变量来分别存储描述头和主体内容其中保存主体内容的变量是一个输出流类型的对象当主体内容的大小小于DiskFileUpload setSizeThreshold方法设置的临界值大小时这个流对象关联到一片内存主体内容将会被保存在内存中当主体内容的数据超过DiskFileUpload setSizeThreshold方法设置的临界值大小时这个流对象关联到硬盘上的一个临时文件主体内容将被保存到该临时文件中临时文件的存储目录由DiskFileUpload setRepositoryPath方法设置临时文件名的格式为 upload_(八位或八位以上的数字) tmp这种形式 FileItem类内部提供了维护临时文件名中的数值不重复的机制以保证了临时文件名的唯一性当应用程序将主体内容保存到一个指定的文件中时或者在FileItem对象被垃圾回收器回收时或者Java虚拟机结束时 Apache文件上传组件都会尝试删除临时文件以尽量保证临时文件能被及时清除
下面介绍FileItem类中的几个常用的方法
isFormField方法
isFormField方法用于判断FileItem类对象封装的数据是否属于一个普通表单字段还是属于一个文件表单字段如果是普通表单字段则返回true否则返回false该方法的完整语法定义如下
public boolean isFormField()
getName方法
getName方法用于获得文件上传字段中的文件名对于图中的第三个分区所示的描述头 getName方法返回的结果为字符串 C:\bg gif如果FileItem类对象对应的是普通表单字段 getName方法将返回null即使用户没有通过网页表单中的文件字段传递任何文件但只要设置了文件表单字段的name属性浏览器也会将文件字段的信息传递给服务器只是文件名和文件内容部分都为空但这个表单字段仍然对应一个FileItem对象此时 getName方法返回结果为空字符串读者在调用Apache文件上传组件时要注意考虑这个情况 getName方法的完整语法定义如下
public String getName()
注意如果用户使用Windows系统上传文件浏览器将传递该文件的完整路径如果用户使用Linux或者Unix系统上传文件浏览器将只传递该文件的名称部分
.getFieldName方法
getFieldName方法用于返回表单字段元素的name属性值也就是返回图中的各个描述头部分中的name属性值例如 name=p中的 p getFieldName方法的完整语法定义如下
public String getFieldName()
write方法
write方法用于将FileItem对象中保存的主体内容保存到某个指定的文件中如果FileItem对象中的主体内容是保存在某个临时文件中该方法顺利完成后临时文件有可能会被清除该方法也可将普通表单字段内容写入到一个文件中但它主要用途是将上传的文件内容保存在本地文件系统中其完整语法定义如下
public void write(File file)
.getString方法
getString方法用于将FileItem对象中保存的主体内容作为一个字符串返回它有两个重载的定义形式
public java lang String getString()
public java lang String getString(java lang String encoding)
throws java io UnsupportedEncodingException
前者使用缺省的字符集编码将主体内容转换成字符串后者使用参数指定的字符集编码将主体内容转换成字符串如果在读取普通表单字段元素的内容时出现了中文乱码现象请调用第二个getString方法并为之传递正确的字符集编码名称
getContentType方法
getContentType方法用于获得上传文件的类型对于图中的第三个分区所示的描述头 getContentType方法返回的结果为字符串 image/gif即 Content Type字段的值部分如果FileItem类对象对应的是普通表单字段该方法将返回null getContentType方法的完整语法定义如下
public String getContentType()
isInMemory方法
isInMemory方法用来判断FileItem类对象封装的主体内容是存储在内存中还是存储在临时文件中如果存储在内存中则返回true否则返回false其完整语法定义如下
public boolean isInMemory()
delete方法
delete方法用来清空FileItem类对象中存放的主体内容如果主体内容被保存在临时文件中 delete方法将删除该临时文件尽管Apache组件使用了多种方式来尽量及时清理临时文件但系统出现异常时仍有可能造成有的临时文件被永久保存在了硬盘中在有些情况下可以调用这个方法来及时删除临时文件其完整语法定义如下
public void delete()
FileUploadException类
在文件上传过程中可能发生各种各样的异常例如网络中断数据丢失等等为了对不同异常进行合适的处理 Apache文件上传组件还开发了四个异常类其中FileUploadException是其他异常类的父类其他几个类只是被间接调用的底层类对于Apache组件调用人员来说只需对FileUploadException异常类进行捕获和处理即可
ServletRequestContext
lishixinzhi/Article/program/Java/hx/201311/26285三、Java文件上传 MultipartRequest无法实例化
jsp文件上传大多采用采用开源项目来简化处理,这里列出常用的两个jar包的实现,并进行比较,说明他们的优缺点和应该注意的问题。
Commons FileUpload,可以在下载,这个包需要Commons IO的支持,可以在下载
com.oreilly.servlet,可以在下载
Commons FileUpload提供三种文件上传处理方式,DiskFileUpload、ServletFileUpload和PortletFileUpload三种方式,其中DiskFileUpload已经在javadoc下已经被标记为过期的方法,建议用ServletFileUpload代替,而PortletFileUpload需要配合portlet-api来使用,所以这里我们只介绍ServletFileUpload,并且这个也是最常用的。
com.oreilly.servlet也提供了三种文件上传的处理方式,MultipartWrapper、MultipartRequest和MultipartParser三种方式,其中MultipartWrapper和MultipartRequest的用法基本相同,并且没有MultipartRequest提供的操作多,所以这里介绍MultipartRequest,MultipartParser和前两者有些不同,可以用来处理某些特殊情况,例如表单中有两个同名的文件上传选择框。
我们暂时称三面三种文件上传方式分别为:ServletFileUpload方式(MultipartTestServlet)、MultipartRequest方式(MultipartTestServlet2)、MultipartParser方式(MultipartTestServlet3)
代码如下:
test.html
<%@ page language="java" import="java.util.*" contentType="text/html;charset=gbk" pageEncoding="gbk"%>
<html>
<body>
<form action="MultipartTestServlet" enctype="multipart/form-data" method="post">
<input type="text" name="username"/><br/>
<input type="file" name="myfile"/><br/>
<input type="file" name="myfile"/><br/>
<input type="submit"/>
</form>
<br/><br/><br/><br/>
<form action="MultipartTestServlet2" enctype="multipart/form-data" method="post">
<input type="text" name="username"/><br/>
<input type="file" name="myfile"/><br/>
<input type="file" name="myfile"/><br/>
<input type="submit"/>
</form>
<br/><br/><br/><br/>
<form action="MultipartTestServlet3" enctype="multipart/form-data" method="post">
<input type="text" name="username"/><br/>
<input type="file" name="myfile"/><br/>
<input type="file" name="myfile"/><br/>
<input type="submit"/>
</form>
</body>
</html>
MultipartTestServlet.java
package com.bug.servlet;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUpload;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.RequestContext;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.servlet.ServletRequestContext;
public class MultipartTestServlet extends HttpServlet{
public MultipartTestServlet(){
super();
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
request.setCharacterEncoding("gbk");
RequestContext requestContext= new ServletRequestContext(request);
if(FileUpload.isMultipartContent(requestContext)){
DiskFileItemFactory factory= new DiskFileItemFactory();
factory.setRepository(new File("c:/tmp/"));
ServletFileUpload upload= new ServletFileUpload(factory);
//upload.setHeaderEncoding("gbk");
upload.setSizeMax(2000000);
List items= new ArrayList();
try{
items= upload.parseRequest(request);
} catch(FileUploadException e1){
System.out.println("文件上传发生错误"+ e1.getMessage());
}
Iterator it= items.iterator();
while(it.hasNext()){
FileItem fileItem=(FileItem) it.next();
if(fileItem.isFormField()){
System.out.println(fileItem.getFieldName()+""+ fileItem.getName()+""+ new String(fileItem.getString().getBytes("iso8859-1"),"gbk"));
}else{
System.out.println(fileItem.getFieldName()+""+
fileItem.getName()+""+
fileItem.isInMemory()+""+
fileItem.getContentType()+""+
fileItem.getSize());
if(fileItem.getName()!=null&& fileItem.getSize()!=0){
File fullFile= new File(fileItem.getName());
File newFile= new File("c:/temp/"+ fullFile.getName());
try{
fileItem.write(newFile);
} catch(Exception e){
e.printStackTrace();
}
}else{
System.out.println("文件没有选择或文件内容为空");
}
}
}
}
}
}
MultipartTestServlet2.java
package com.bug.servlet;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;
public class MultipartTestServlet2 extends HttpServlet{
public MultipartTestServlet2(){
super();
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
//request.setCharacterEncoding("gbk");不起作用
System.out.println("start");
MultipartRequest multi= new MultipartRequest(request,"c:/tmp/", 2*1024*1024,"gbk", new DefaultFileRenamePolicy());
System.out.println("start");
Enumeration filesName= multi.getFileNames();
Enumeration paramsName= multi.getParameterNames();
while(paramsName.hasMoreElements()){
String paramName=(String) paramsName.nextElement();
System.out.println(multi.getParameter(paramName));
}
while(filesName.hasMoreElements()){
String fileName=(String) filesName.nextElement();
System.out.println(multi.getFilesystemName(fileName)+""+
multi.getOriginalFileName(fileName)+""+
multi.getContentType(fileName)+"");
if(multi.getFilesystemName(fileName)!=null&&!multi.getFilesystemName(fileName).equals(""))
System.out.println(multi.getFile(fileName).toURI());
}
}
}
MultipartTestServlet3.java
package com.bug.servlet;
import java.io.File;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.oreilly.servlet.multipart.FilePart;
import com.oreilly.servlet.multipart.MultipartParser;
import com.oreilly.servlet.multipart.ParamPart;
import com.oreilly.servlet.multipart.Part;
public class MultipartTestServlet3 extends HttpServlet{
public MultipartTestServlet3(){
super();
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
MultipartParser mp= new MultipartParser(request, 2*1024*1024, false, false,"gbk");
Part part;
while((part= mp.readNextPart())!= null){
String name= part.getName();
if(part.isParam()){
ParamPart paramPart=(ParamPart) part;
String value= paramPart.getStringValue();
System.out.println("param: name="+ name+"; value="+ value);
}
else if(part.isFile()){
// it's a file part
FilePart filePart=(FilePart) part;
String fileName= filePart.getFileName();
if(fileName!= null){
long size= filePart.writeTo(new File("c:/tmp/"));
System.out.println("file: name="+ name+"; fileName="+ fileName+
", filePath="+ filePart.getFilePath()+
", contentType="+ filePart.getContentType()+
", size="+ size);
}
else{
System.out.println("file: name="+ name+"; EMPTY");
}
System.out.flush();
}
}
}
}
web.xml中加入
<servlet>
<servlet-name>MultipartTestServlet</servlet-name>
<servlet-class>com.bug.servlet.MultipartTestServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>MultipartTestServlet2</servlet-name>
<servlet-class>com.bug.servlet.MultipartTestServlet2</servlet-class>
</servlet>
<servlet>
<servlet-name>MultipartTestServlet3</servlet-name>
<servlet-class>com.bug.servlet.MultipartTestServlet3</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MultipartTestServlet</servlet-name>
<url-pattern>/MultipartTestServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>MultipartTestServlet2</servlet-name>
<url-pattern>/MultipartTestServlet2</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>MultipartTestServlet3</servlet-name>
<url-pattern>/MultipartTestServlet3</url-pattern>
</servlet-mapping>
问题1、中文问题:
三种凡是都可以通过自己的方法来设置encoding为gbk开处理和解决中文问题,包括初始化的时候传入gbk作为参数,或是是初始化后通过setEncoding的方式来实现。
另外ServletFileUpload方式也可以通过request.setCharacterEncoding("gbk");的方式来实现,而其它两种方式不支持这种方式。
问题2、文件大小限制
ServletFileUpload方式可以设置文件大小限制,也可以不用设置,例子中的upload.setSizeMax(2000000)就可以注释掉。如果设置upload.setSizeMax(-1),表明不限制上传的大小。文档中没有指明默认的限制的多少,我在不设置的情况下上传了一个9M的东西,可以上传,估计默认是不限制大小的。
而MultipartRequest方式和MultipartParser方式是必须设置文件的上传文件的大小限制的,如果不设置,默认是1M的大小限制。
问题3、文件上传发生错误
如果文件上传过程中发生任何错误,或者是文件的大小超出了范围,系统都将抛出错误。
ServletFileUpload方式在upload.parseRequest(request)时抛出错误
MultipartRequest方式在new MultipartRequest(。。。)时抛出错误
MultipartParser方式在new MultipartParser(。。。)时抛出错误
问题4、上传同名文件时,他们保存到临时目录是的冲突问题
ServletFileUpload方式,不会有冲突,系统会把上传得文件按照一定的规则重新命名,保证不会冲突
MultipartParser方式,会产生冲突,系统会把文件按照上传时的文件名,保存到临时目录下,如果两个用会同时上传文件名相同的文件,那么就可能会产生冲突,一方把另一方的临时文件给替换了。
MultipartRequest方式,在初始化时如果提供了一个名称转换策略,就不会有冲突,如果不提桶,就会有冲突。在上面的例子中我们提供了一个new DefaultFileRenamePolicy()保证了文件名不会有冲突发生。
问题5:表单中有两个同名的文件上传选择框,就像我们例子中的myfile一样,每个表单中有两个name=“myfile”的上传框
ServletFileUpload方式,可以处理,可以分别得到他们各自的文件,
MultipartRequest方式,不可以处理,会发生冲突,会有一个上传框的文件覆盖了另外一个。
MultipartParser方式,可以处理,可以分别得到他们各自的文件,
备注:
代码比较乱,主要是为了说明他们间的区别。他们的详细地使用说明还是要参考他的javadoc和domo。