掌控上传进度的AJAX Upload.docx
- 文档编号:12883515
- 上传时间:2023-06-08
- 格式:DOCX
- 页数:19
- 大小:124.20KB
掌控上传进度的AJAX Upload.docx
《掌控上传进度的AJAX Upload.docx》由会员分享,可在线阅读,更多相关《掌控上传进度的AJAX Upload.docx(19页珍藏版)》请在冰点文库上搜索。
掌控上传进度的AJAXUpload
掌控上传进度的AJAXUpload
摘要:
2006年底Google了一下AJAXUpload实现,结果没有发现很完整的Java实现。
硕果仅存的就是TELIO公司的Pierre-Alexandre发表的《AJAXUploadprogressmonitorforCommons-FileUploadExample》一文。
虽然文中完成Upload工作的是Common-FileUpload组件,但在其代码中没有1.2版本所提供的Listener功能,这就对检测文件上传情况造成了困难...
动机:
2006年底Google了一下AJAXUpload实现,结果没有发现很完整的Java实现。
硕果仅存的就是TELIO公司的Pierre-Alexandre发表的《AJAXUploadprogressmonitorforCommons-FileUploadExample》文中提供的ajax-upload-1.0.war。
虽然上文中完成Upload工作的是Apache的Common-FileUpload组件,但在其代码中所使用的FileUpload1.1版本并没有1.2版本所提供的上传处理Listener功能,这就对检测文件上传情况造成了困难。
我想正是这个原因致使Pierre-Alexandre使用了DWR+MonitoredDiskFileItem、MonitoredDiskFileItemFactory类(分别继承DiskFileItem、DiskFileItemFactory)的方式:
前者负责在web客户端进行RemoteCall;后者在进行文件数据读取时统计数据总量、读取数据量、处理文件总数,并保存于Session中,以供web客户端通过DWR远程调用UploadMonitor类的getUploadInfo方法进行轮询(Poll)。
从本人观点出发,Pierre-Alexandre实现的不足之处:
1.没有用户取消上传功能;
2.完全的DWR实现,没有使用Prototype,对于不会使用DWR的开发者来讲有一定的知识局限性,而且由于DWR的个性而造成不便将此实现集成到项目中。
Prototype+Servlet的实现:
Prototype+Servlet的Example
所以出于研究Prototype之目的,本人经过仔细思考,尝试实现了一个Prototype+Servlet的简单Example。
其工作流程很简单:
1.在Form提交上传文件Field的同时,使用AJAX周期性地从Servlet轮询上传状态信息;
2.然后,根据此信息更新进度条和相关文字,及时反映文件传输状态;
3.如果用户取消上传操作,则进行相应的现场清理工作:
删除已经上传的文件,在Form提交页面中显示相关信息;
4.如果上传完毕,在Form提交页面中显示已经上传的文件内容(或链接),也可以与一些AJAXSlideShow应用结合在一起。
服务器端代码:
Bean序列化/反序列化工作:
XmlUnSerializer这个类虽然不能够通吃任何模样的Bean,但应付一般的Bean、具有Collection类型属性的Bean和BeanList来讲还是够用的。
{XmlUnSerializer类的核心方法serializeBean和serializeBeanList}:
/**
*将bean系列化为UTF-8编码的xml
*@parambeanObj
*@return
*@throwsIOException
*/
publicstaticStringserializeBean(ObjectbeanObj)throwsIOException{
…
}
/**
*将bean列表序列化为UTF-8编码的xml
*@parambeanObj
*@return
*@throwsIOException
*/
publicstaticStringserializeBeanList(ObjectbeanListObj)throwsIOException{
…
}
文件上传状态Bean:
使用FileUploadStatus这个类记录文件上传状态,并将其作为服务器端与web客户端之间通信的媒介物:
通过对这个类对象进行XML序列化作为服务器回应发送给web客户端,web客户端使用JavaScript对其进行反序列化处理获得JavaScript版本的文件上传状态对象。
{FileUploadStatus的属性}:
//上传总量
privatelonguploadTotalSize=0;
//读取上传总量
privatelongreadTotalSize=0;
//当前上传文件号
privateintcurrentUploadFileNum=0;
//成功读取上传文件数
privateintsuccessUploadFileCount=0;
//状态
privateStringstatus="";
//处理起始时间
privatelongprocessStartTime=0l;
//处理终止时间
privatelongprocessEndTime=0l;
//处理执行时间
privatelongprocessRunningTime=0l;
//上传文件URL列表
privateListuploadFileUrlList=newArrayList();
//取消上传
privatebooleancancel=false;
//上传base目录
privateStringbaseDir="";
文件上传状态监视工作:
使用Common-FileUpload1.2版本(20070103)。
此版本与1.1版的区别在于提供了能够监视文件上传情况的ProcessListener接口,使开发者通过FileUploadBase类对象的setProcessListener方法植入自己的Listener,而且实现这个Listener很简单。
{FileUploadListener主要方法update}:
/**
*更新状态
*@parampBytesRead读取字节总数
*@parampContentLength数据总长度
*@parampItems当前正在被读取的field号
*/
publicvoidupdate(longpBytesRead,longpContentLength,intpItems){
FileUploadStatusfuploadStatus=BackGroundService.takeOutFileUploadStatusBean(this.session);
logger.debug("当前正在处理第"+pItems+"个文件");
fuploadStatus.setUploadTotalSize(pContentLength);
//读取完成
if(pContentLength==-1){
logger.debug("读取完成:
读取了"+pBytesRead+"bytes.");
fuploadStatus.setStatus("完成对"+pItems+"个文件的读取:
读取了"+pBytesRead+"bytes.");
fuploadStatus.setReadTotalSize(pBytesRead);
fuploadStatus.setSuccessUploadFileCount(pItems);
fuploadStatus.setProcessEndTime(System.currentTimeMillis());
fuploadStatus.setProcessRunningTime(fuploadStatus.getProcessEndTime());
//读取中
}else{
logger.debug("读取进行中:
已经读取了"+pBytesRead+"/"+pContentLength+"bytes.");
fuploadStatus.setStatus("当前正在处理第"+pItems+"个文件:
已经读取了"+pBytesRead+"/"+pContentLength+"bytes.");
fuploadStatus.setReadTotalSize(pBytesRead);
fuploadStatus.setCurrentUploadFileNum(pItems);
fuploadStatus.setProcessRunningTime(System.currentTimeMillis());
}
BackGroundService.storeFileUploadStatusBean(this.session,fuploadStatus);
}
很清楚,我也把FileUploadStatus这个Bean存取于Session中。
Servlet实现:
BackGroundService这个Servlet类负责接收FormPost数据、回应状态轮询请求、处理取消文件上传的请求。
尽管可以把这些功能相互分离开来(比如构造一个FileUploadManager类),但出于简单明了、便于阅读之目的,还是将它们放到Servlet中,只是由不同的方法进行分割。
{BackGroundService中的processFileUpload方法用于处理文件上传请求}:
/**
*处理文件上传
*@paramrequest
*@paramresponse
*@throwsIOException
*@throwsServletException
*/
privatevoidprocessFileUpload(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{
DiskFileItemFactoryfactory=newDiskFileItemFactory();
//设置内存阀值,超过后写入临时文件
factory.setSizeThreshold(10240000);
//设置临时文件存储位置
factory.setRepository(newFile(request.getRealPath("/upload/temp")));
ServletFileUploadupload=newServletFileUpload(factory);
//设置单个文件的最大上传size
upload.setFileSizeMax(10240000);
//设置整个request的最大size
upload.setSizeMax(10240000);
upload.setProgressListener(newFileUploadListener(request.getSession()));
//保存初始化后的FileUploadStatusBean
storeFileUploadStatusBean(request.getSession(),initFileUploadStatusBean(request));
StringforwardURL="";
try{
Listitems=upload.parseRequest(request);
//获得返回url
for(inti=0;i FileItemitem=(FileItem)items.get(i); if(item.isFormField()){ logger.debug("formField["+item.getFieldName()+"]="+item.getString()); forwardURL=item.getString(); break; } } //处理文件上传 for(inti=0;i FileItemitem=(FileItem)items.get(i); //取消上传 if(takeOutFileUploadStatusBean(request.getSession()).getCancel()){ deleteUploadedFile(request); break; } //保存文件 elseif(! item.isFormField()&&item.getName().length()>0){ StringfileName=takeOutFileName(item.getName()); logger.debug("处理文件["+fileName+"]: 保存路径为" +request.getRealPath(UPLOAD_DIR)+File.separator+fileName); FileuploadedFile=newFile(request.getRealPath(UPLOAD_DIR)+File.separator+fileName); item.write(uploadedFile); //更新上传文件列表 FileUploadStatusfUploadStatus=takeOutFileUploadStatusBean(request.getSession()); fUploadStatus.getUploadFileUrlList().add(fileName); storeFileUploadStatusBean(request.getSession(),fUploadStatus); Thread.sleep(500); } } }catch(FileUploadExceptione){ logger.error("上传文件时发生错误: "+e.getMessage()); e.printStackTrace(); uploadExceptionHandle(request,"上传文件时发生错误: "+e.getMessage()); }catch(Exceptione){ //TODOAuto-generatedcatchblock 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方法用于处理对文件上传状态的轮询请求}: /** *回应上传状态查询 *@paramrequest *@paramresponse *@throwsIOException */ privatevoidresponseFileUploadStatusPoll(HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException{ 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方法用于处理取消文件上传的请求}: /** *处理取消文件上传 *@paramrequest *@paramresponse *
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 掌控上传进度的AJAX Upload 掌控 上传 进度 AJAX
![提示](https://static.bingdoc.com/images/bang_tan.gif)