在上一篇文章《
利用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();
}
按照上面处理的话,很是不爽,因此我想包装一下,使得使用起来符合我们的习惯。
总体设计思想:
根据以上要求,我写出了一个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中,关键是给出一个想法,我们可以对他进行包装变更,使其更适合我们的系统。



























总体设计思想:
1.我们可以像以前那样,传入控件的name,就可以取得该控件的value,因此我想可以遍历所有FileItem,然后把他们存入一个Map中(key中存入fieldname,value中存入该控件的value),这样就可以达到以上目的了。
2.在该包装类中,我们还要可以设置一些值,从而我们可以更改commons fileupload中的一些配置。
具体实现:
2.在该包装类中,我们还要可以设置一些值,从而我们可以更改commons fileupload中的一些配置。
根据以上要求,我写出了一个MutiFileUpload类,代码如下,稍后再做详细解释。
















































































































































































































































































以上代码很简单,看过commons FileUpload组件API的程序员,应该都能看明白。值得注意一下的是:编码问题(setHeaderEncoding),这个方法是从 FileUploadBase类里继承的, 根据其说明,当读取上传表单的各部分时会用到该encoding,如果没有指定encoding则使用系统缺省的encoding。建议在这里设置成utf-8,并把jsp的charset也设置成utf-8,否则可能会出现乱码。
测试demo
好了,下面我就写个简单的demo吧,说明一下MutiFileUpload的用法。
1.新建一个jsp页面,注意设置form表单的enctype,如下:

















































好了,先写到这里吧,具体应用时,我们可能需要很多变通,比如集成到spring,hibernate中,关键是给出一个想法,我们可以对他进行包装变更,使其更适合我们的系统。