对commons fileupload组件的简单封装
在上一篇文章《
利用Jakarta commons fileupload组件实现多文件上传》中,我介绍了commons fileupload组件的基本原理和实现方法。但是在实际操作中,我们需要分析每个FileItem,然后从该FileItem中读取该控件的name和value,显然这不符合我们的习惯。比如我们在页面上有个text文本框:
<input type="text" name="possess">
我们要取得possess传过来的value,一般我们是这么写的:
String possess = request.getParameter("possess")
但是在commons fileupload中我们却需要这么处理:
DiskFileItemFactory factory = new DiskFileItemFactory();
//Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
String possess = "";
![]()
try ...{
List items = upload.parseRequest(request);
Iterator iterator = items.iterator();
![]()
while(iterator.hasNext())...{
FileItem item = (FileItem)iterator.next();
![]()
if(item.isFormField())...{
String fieldName = item.getFieldName();
String value = item.getString();
![]()
if(fieldName.equals("possess"))...{
possess = value;
}
}
}
![]()
} catch (FileUploadException e) ...{
e.printStackTrace();
}
按照上面处理的话,很是不爽,因此我想包装一下,使得使用起来符合我们的习惯。
总体设计思想:
1.我们可以像以前那样,传入控件的name,就可以取得该控件的value,因此我想可以遍历所有FileItem,然后把他们存入一个Map中(key中存入fieldname,value中存入该控件的value),这样就可以达到以上目的了。
2.在该包装类中,我们还要可以设置一些值,从而我们可以更改commons fileupload中的一些配置。
具体实现: 根据以上要求,我写出了一个MutiFileUpload类,代码如下,稍后再做详细解释。
package chb.commons.fileupload.web;
![]()
import java.util.HashMap;
![]()
import java.util.Iterator;
![]()
import java.util.List;
![]()
import java.util.Map;
![]()
import javax.servlet.http.HttpServlet;
![]()
import javax.servlet.http.HttpServletRequest;
![]()
![]()
import org.apache.commons.fileupload.FileItem;
![]()
import org.apache.commons.fileupload.FileUploadException;
![]()
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
![]()
import org.apache.commons.fileupload.servlet.ServletFileUpload;
![]()
![]()
![]()
![]()
/** *//**
![]()
* @author chb
![]()
*
![]()
*/
![]()
![]()
public class MutiFileUpload extends HttpServlet...{
![]()
private static final long serialVersionUID = 670829239023754119L;
![]()
![]()
protected Map<String, String> parameters;//保存普通form表单域
![]()
protected Map<String, FileItem> files;//保存上传的文件
![]()
![]()
![]()
/** *//**
![]()
* The directory in which uploaded files will be stored, if stored on disk.
![]()
*/
![]()
private int sizeThreshold = DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD;
![]()
![]()
![]()
/** *//**
![]()
* The maximum size permitted for the complete request, as opposed to
![]()
* {@link #fileSizeMax}. A value of -1 indicates no maximum.
![]()
*/
![]()
private long sizeMax = -1;
![]()
![]()
private String encoding = "utf-8";//字符编码,当读取上传表单的各部分时会用到该encoding
![]()
![]()
![]()
public String getEncoding() ...{
![]()
return encoding;
![]()
}
![]()
![]()
public void setEncoding(String encoding) ...{
![]()
this.encoding = encoding;
![]()
}
![]()
![]()
public long getSizeMax() ...{
![]()
return sizeMax;
![]()
}
![]()
![]()
public void setSizeMax(long sizeMax) ...{
![]()
this.sizeMax = sizeMax;
![]()
}
![]()
![]()
public int getSizeThreshold() ...{
![]()
return sizeThreshold;
![]()
}
![]()
![]()
public void setSizeThreshold(int sizeThreshold) ...{
![]()
this.sizeThreshold = sizeThreshold;
![]()
}
![]()
![]()
public void parse(HttpServletRequest request)...{
![]()
parameters = new HashMap<String, String>();
![]()
files = new HashMap<String, FileItem>();
![]()
//Create a factory for disk-based file items
![]()
DiskFileItemFactory factory = new DiskFileItemFactory();
![]()
![]()
![]()
//Set factory constraints
![]()
factory.setSizeThreshold(sizeThreshold);
![]()
//factory.setRepository(repository);
![]()
![]()
![]()
//Create a new file upload handler
![]()
ServletFileUpload upload = new ServletFileUpload(factory);
![]()
![]()
![]()
//Set overall request size constraint
![]()
upload.setSizeMax(sizeMax);
![]()
upload.setHeaderEncoding(encoding);
![]()
![]()
![]()
![]()
try ...{
![]()
List items = upload.parseRequest(request);
![]()
Iterator iterator = items.iterator();
![]()
![]()
while(iterator.hasNext())...{
![]()
FileItem item = (FileItem)iterator.next();
![]()
![]()
if(item.isFormField())...{
![]()
String fieldName = item.getFieldName();
![]()
String value = item.getString();
![]()
parameters.put(fieldName, value);
![]()
![]()
}else...{
![]()
String fieldName = item.getFieldName();
![]()
files.put(fieldName, item);
![]()
}
![]()
}
![]()
![]()
} catch (FileUploadException e) ...{
![]()
e.printStackTrace();
![]()
}
![]()
}
![]()
![]()
/** *//** 得到上传文件的文件名
![]()
* @param item
![]()
* @return
![]()
*/
![]()
![]()
public String getFileName(FileItem item)...{
![]()
String fileName = item.getName();
![]()
fileName = replace(fileName,"/","/");
![]()
fileName = fileName.substring(fileName.lastIndexOf("/")+1);
![]()
return fileName;
![]()
}
![]()
![]()
/** *//**字符串替换
![]()
* @param source
![]()
* @param oldString
![]()
* @param newString
![]()
* @return
![]()
*/
![]()
![]()
public static String replace(String source, String oldString, String newString) ...{
![]()
StringBuffer output = new StringBuffer();
![]()
![]()
![]()
int lengthOfSource = source.length();
![]()
int lengthOfOld = oldString.length();
![]()
int posStart = 0;
![]()
int pos;
![]()
![]()
![]()
![]()
while ((pos = source.indexOf(oldString, posStart)) >= 0) ...{
![]()
output.append(source.substring(posStart, pos));
![]()
output.append(newString);
![]()
posStart = pos + lengthOfOld;
![]()
}
![]()
![]()
if (posStart < lengthOfSource) ...{
![]()
output.append(source.substring(posStart));
![]()
}
![]()
return output.toString();
![]()
}
![]()
![]()
![]()
}
![]()
![]()
以上代码很简单,看过commons FileUpload组件API的程序员,应该都能看明白。值得注意一下的是:编码问题(setHeaderEncoding),这个方法是从
FileUploadBase类里继承的,根据其说明,当读取上传表单的各部分时会用到该encoding,如果没有指定encoding则使用系统缺省的encoding。建议在这里设置成utf-8,并把jsp的charset也设置成utf-8,否则可能会出现乱码。
测试demo
好了,下面我就写个简单的demo吧,说明一下MutiFileUpload的用法。
1.新建一个jsp页面,注意设置form表单的enctype,如下:
<form id="form1" method="post" action="../servlet/UploadServlet" enctype="multipart/form-data">
<tr>
<td width="25%" align="right">上传图片:</td>
<td>
<input id="file1" type="file" NAME="file1" style="width:300px;">
</td>
</tr>
<tr>
<td width="25%" align="right">上传音频:</td>
<td>
<input id="file2" type="file" NAME="file2" style="width:300px;">
</td>
</tr>
<tr align="center" valign="middle">
<td height="60" colspan="2">
<input type="submit" id="BtnOK" value="确认上传">
<button onclick="javascript:window.opener == null;window.close();">取消上传</button> </td>
</tr>
<tr align="center" valign="middle">
<td height="60" colspan="2">
<input type="text" name="possess" value="private">
</td>
</tr>
</form>
2.新建一个UploadServlet并继承自MutiFileUpload,如下:
![]()
public class UploadServlet extends MutiFileUpload ...{
}
3.然后在post方法中如下处理:
public void doPost(HttpServletRequest request, HttpServletResponse response)
![]()
throws ServletException, IOException ...{
parse(request);
System.out.println(parameters.get("possess"));
Iterator iterator = files.values().iterator();
![]()
while(iterator.hasNext())...{
FileItem item = (FileItem) iterator.next();
String fileName = getFileName(item);
File file = new File("/root/upload/"+fileName);
![]()
try ...{
item.write(file);
![]()
} catch (Exception e) ...{
e.printStackTrace();
}
}
}
选择上传文件,然后我们就可以在/root/upload下看到我们上传的文件了。
好了,先写到这里吧,具体应用时,我们可能需要很多变通,比如集成到spring,hibernate中,关键是给出一个想法,我们可以对他进行包装变更,使其更适合我们的系统。