1、掌控上传进度的AJAX Upload掌控上传进度的AJAX Upload摘要:2006年底Google了一下AJAX Upload实现,结果没有发现很完整的Java实现。硕果仅存的就是TELIO公司的Pierre-Alexandre发表的AJAX Upload progress monitor for Commons-FileUpload Example一文。虽然文中完成Upload工作的是Common-FileUpload组件,但在其代码中没有1.2版本所提供的Listener功能,这就对检测文件上传情况造成了困难.动机:2006年底Google了一下AJAX Upload实现,结果没有发现
2、很完整的Java实现。硕果仅存的就是TELIO公司的Pierre-Alexandre发表的AJAX Upload progress monitor for Commons-FileUpload Example文中提供的ajax-upload-1.0.war。虽然上文中完成Upload工作的是Apache的Common-FileUpload组件,但在其代码中所使用的FileUpload1.1版本并没有1.2版本所提供的上传处理Listener功能,这就对检测文件上传情况造成了困难。我想正是这个原因致使Pierre-Alexandre使用了DWR+MonitoredDiskFileItem、Mon
3、itoredDiskFileItemFactory类(分别继承DiskFileItem、DiskFileItemFactory)的方式:前者负责在web客户端进行Remote Call;后者在进行文件数据读取时统计数据总量、读取数据量、处理文件总数,并保存于Session中,以供web客户端通过DWR远程调用UploadMonitor类的getUploadInfo方法进行轮询(Poll)。从本人观点出发,Pierre-Alexandre实现的不足之处:1.没有用户取消上传功能;2.完全的DWR实现,没有使用Prototype,对于不会使用DWR的开发者来讲有一定的知识局限性,而且由于DWR的个
4、性而造成不便将此实现集成到项目中。Prototype+Servlet的实现:Prototype+Servlet的Example所以出于研究Prototype之目的,本人经过仔细思考,尝试实现了一个Prototype+Servlet的简单Example。其工作流程很简单:1.在Form提交上传文件Field的同时,使用AJAX周期性地从Servlet轮询上传状态信息;2.然后,根据此信息更新进度条和相关文字,及时反映文件传输状态;3.如果用户取消上传操作,则进行相应的现场清理工作:删除已经上传的文件,在Form提交页面中显示相关信息;4.如果上传完毕,在Form提交页面中显示已经上传的文件内容(
5、或链接),也可以与一些AJAX SlideShow应用结合在一起。服务器端代码:Bean序列化/反序列化工作:XmlUnSerializer这个类虽然不能够通吃任何模样的Bean,但应付一般的Bean、具有Collection类型属性的Bean和Bean List来讲还是够用的。XmlUnSerializer类的核心方法serializeBean和serializeBeanList:/* * 将bean系列化为UTF-8编码的xml * param beanObj * return * throws IOException */public static String serializeBea
6、n(Object beanObj) throws IOException/* * 将bean列表序列化为UTF-8编码的xml * param beanObj * return * throws IOException */public static String serializeBeanList(Object beanListObj) throws IOException文件上传状态Bean:使用FileUploadStatus这个类记录文件上传状态,并将其作为服务器端与web客户端之间通信的媒介物:通过对这个类对象进行XML序列化作为服务器回应发送给web客户端,web客户端使用Java
7、Script对其进行反序列化处理获得JavaScript版本的文件上传状态对象。FileUploadStatus的属性:/上传总量private long uploadTotalSize=0;/读取上传总量private long readTotalSize=0;/当前上传文件号private int currentUploadFileNum=0;/成功读取上传文件数private int successUploadFileCount=0;/状态private String status=;/处理起始时间private long processStartTime=0l;/处理终止时间priva
8、te long processEndTime=0l;/处理执行时间private long processRunningTime=0l;/上传文件URL列表private List uploadFileUrlList=new ArrayList();/取消上传private boolean cancel=false;/上传base目录private String baseDir=;文件上传状态监视工作:使用Common-FileUpload 1.2版本(20070103)。此版本与1.1版的区别在于提供了能够监视文件上传情况的ProcessListener接口,使开发者通过FileUpload
9、Base类对象的setProcessListener方法植入自己的Listener,而且实现这个Listener很简单。FileUploadListener主要方法update:/* * 更新状态 * param pBytesRead 读取字节总数 * param pContentLength 数据总长度 * param pItems 当前正在被读取的field号 */public void update(long pBytesRead, long pContentLength, int pItems)FileUploadStatus fuploadStatus=BackGroundServi
10、ce.takeOutFileUploadStatusBean(this.session);logger.debug(当前正在处理第 + pItems+个文件);fuploadStatus.setUploadTotalSize(pContentLength);/读取完成if (pContentLength = -1) logger.debug(读取完成:读取了 + pBytesRead + bytes.); fuploadStatus.setStatus(完成对 + pItems+个文件的读取:读取了 + pBytesRead + bytes.); fuploadStatus.setReadTo
11、talSize(pBytesRead); fuploadStatus.setSuccessUploadFileCount(pItems); fuploadStatus.setProcessEndTime(System.currentTimeMillis(); fuploadStatus.setProcessRunningTime(fuploadStatus.getProcessEndTime();/读取中 else logger.debug(读取进行中:已经读取了 + pBytesRead + / + pContentLength+ bytes.); fuploadStatus.setStat
12、us(当前正在处理第 + pItems+个文件:已经读取了 + pBytesRead + / + pContentLength+ bytes.); fuploadStatus.setReadTotalSize(pBytesRead); fuploadStatus.setCurrentUploadFileNum(pItems); fuploadStatus.setProcessRunningTime(System.currentTimeMillis();BackGroundService.storeFileUploadStatusBean(this.session,fuploadStatus);
13、很清楚,我也把FileUploadStatus这个Bean存取于Session中。Servlet实现:BackGroundService这个Servlet类负责接收Form Post数据、回应状态轮询请求、处理取消文件上传的请求。尽管可以把这些功能相互分离开来(比如构造一个FileUploadManager类),但出于简单明了、便于阅读之目的,还是将它们放到Servlet中,只是由不同的方法进行分割。BackGroundService中的processFileUpload方法用于处理文件上传请求:/* * 处理文件上传 * param request * param response * th
14、rows IOException * throws ServletException */private void processFileUpload(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOExceptionDiskFileItemFactory factory = new DiskFileItemFactory();/设置内存阀值,超过后写入临时文件factory.setSizeThreshold(10240000);/设置临时文件存储位置factory.set
15、Repository(new File(request.getRealPath(/upload/temp);ServletFileUpload upload = new ServletFileUpload(factory);/设置单个文件的最大上传sizeupload.setFileSizeMax(10240000);/设置整个request的最大sizeupload.setSizeMax(10240000);upload.setProgressListener(new FileUploadListener(request.getSession();/保存初始化后的FileUploadStat
16、us BeanstoreFileUploadStatusBean(request.getSession(),initFileUploadStatusBean(request);String forwardURL=;try List items = upload.parseRequest(request);/获得返回urlfor(int i=0;iitems.size();i+)FileItem item=(FileItem)items.get(i);if (item.isFormField()logger.debug(form Field+item.getFieldName()+=+item.
17、getString();forwardURL=item.getString();break;/处理文件上传for(int i=0;i0)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.wri
18、te(uploadedFile);/更新上传文件列表FileUploadStatus fUploadStatus=takeOutFileUploadStatusBean(request.getSession();fUploadStatus.getUploadFileUrlList().add(fileName);storeFileUploadStatusBean(request.getSession(),fUploadStatus);Thread.sleep(500); catch (FileUploadException e) logger.error(上传文件时发生错误:+e.getMes
19、sage();e.printStackTrace();uploadExceptionHandle(request,上传文件时发生错误:+e.getMessage(); catch (Exception e) / TODO Auto-generated catch blocklogger.error(保存上传文件时发生错误:+e.getMessage();e.printStackTrace();uploadExceptionHandle(request,保存上传文件时发生错误:+e.getMessage();if (forwardURL.length()=0)forwardURL=DEFAULT
20、_UPLOAD_FAILURE_URL;request.getRequestDispatcher(forwardURL).forward(request,response);BackGroundService中的responseFileUploadStatusPoll方法用于处理对文件上传状态的轮询请求:/* * 回应上传状态查询 * param request * param response * throws IOException */private void responseFileUploadStatusPoll(HttpServletRequest request,HttpServ
21、letResponse response) throws IOExceptionresponse.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 *
copyright@ 2008-2023 冰点文库 网站版权所有
经营许可证编号:鄂ICP备19020893号-2