很清楚,我也把FileUploadStatus这个Bean存取于Session中。
Servlet实现:BackGroundService这个Servlet类负责接收Form Post数据、回应状态轮询请求、处理取消文件上传的请求。尽管可以把这些功能相互分离开来(比如构造一个FileUploadManager类),但出于简单明了、便于阅读之目的,还是将它们放到Servlet中,只是由不同的方法进行分割。
{BackGroundService中的processFileUpload方法用于处理文件上传请求}:
/**
* 处理文件上传
* @param request
* @param response
* @throws IOException
* @throws ServletException
*/
private void processFileUpload(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
DiskFileItemFactory factory = new DiskFileItemFactory();
//设置内存阀值,超过后写入临时文件
factory.setSizeThreshold(10240000);
//设置临时文件存储位置
factory.setRepository(new File(request.getRealPath("/upload/temp")));
ServletFileUpload upload = new ServletFileUpload(factory);
//设置单个文件的最大上传size
upload.setFileSizeMax(10240000);
//设置整个request的最大size
upload.setSizeMax(10240000);
upload.setProgressListener(new FileUploadListener(request.getSession()));
//保存初始化后的FileUploadStatus Bean
storeFileUploadStatusBean(request.getSession(),initFileUploadStatusBean(request));
String forwardURL="";
try {
List items = upload.parseRequest(request);
//获得返回url
for(int i=0;i<items.size();i++){
FileItem item=(FileItem)items.get(i);
if (item.isFormField()){
logger.debug("form Field["+item.getFieldName()+"]="+item.getString());
forwardURL=item.getString();
break;
}
}
//处理文件上传
for(int i=0;i<items.size();i++){
FileItem item=(FileItem)items.get(i);
//取消上传
if (takeOutFileUploadStatusBean(request.getSession()).getCancel()){
deleteUploadedFile(request);
break;
}
//保存文件
else if (!item.isFormField() && item.getName().length()>0){
String fileName=takeOutFileName(item.getName());
logger.debug("处理文件["+fileName+"]:保存路径为"
+request.getRealPath(UPLOAD_DIR)+File.separator+fileName);
File uploadedFile =
new File(request.getRealPath(UPLOAD_DIR)+File.separator+fileName);
item.write(uploadedFile);
//更新上传文件列表
FileUploadStatus fUploadStatus=takeOutFileUploadStatusBean
(request.getSession());
fUploadStatus.getUploadFileUrlList().add(fileName);
storeFileUploadStatusBean(request.getSession(),fUploadStatus);
Thread.sleep(500);
}
}
} catch (FileUploadException e) {
logger.error("上传文件时发生错误:"+e.getMessage());
e.printStackTrace();
uploadExceptionHandle(request,"上传文件时发生错误:"+e.getMessage());
} catch (Exception e) {
// TODO Auto-generated catch block
logger.error("保存上传文件时发生错误:"+e.getMessage());
e.printStackTrace();
uploadExceptionHandle(request,"保存上传文件时发生错误:"+e.getMessage());
}
if (forwardURL.length()==0){
forwardURL=DEFAULT_UPLOAD_FAILURE_URL;
}
request.getRequestDispatcher(forwardURL).forward(request,response);
}
{BackGroundService中的responseFileUploadStatusPoll方法用于处理对文件上传状态的轮询请求}:
/**
* 回应上传状态查询
* @param request
* @param response
* @throws IOException
*/
private void responseFileUploadStatusPoll(HttpServletRequest request,HttpServletResponse response)
throws IOException{
response.setContentType("text/xml");
response.setCharacterEncoding("UTF-8");
response.setHeader("Cache-Control", "no-cache");
logger.debug("发送上传状态回应");
response.getWriter().write(XmlUnSerializer.serializeBean(
request.getSession().getAttribute(UPLOAD_STATUS)));
}
{BackGroundService中的processCancelFileUpload方法用于处理取消文件上传的请求}:
/**
* 处理取消文件上传
* @param request
* @param response
* @throws IOException
*/
private void processCancelFileUpload(HttpServletRequest request,HttpServletResponse response)
throws IOException{
FileUploadStatus fUploadStatus=(FileUploadStatus)request.getSession().getAttribute(UPLOAD_STATUS);
fUploadStatus.setCancel(true);
request.getSession().setAttribute(UPLOAD_STATUS, fUploadStatus);
responseFileUploadStatusPoll(request,response);
}
Web客户端代码:

Prototype给开发者更多的自由选择
web客户端使用了基于Prototype的AjaxWrapper类和XMLDomForAjax类,前者实现了对Ajax.Request功能的封装,而后者实现了对来自服务器的XML Response的反序列化(反序列化为JavaScript对象)。
更多内容请看PCdog.com--Ajax技术专题
