AJAX实现基于WEB的文件上传的进度控制

前端之家收集整理的这篇文章主要介绍了AJAX实现基于WEB的文件上传的进度控制前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

转帖:http://blog.csdn.net/liuzuochen/article/details/1516522#d20101

  • 1.引言

  • 2.实现代码

    • 2.2.1. AjaxWrapper.js

    • 2.2.2. fileUpload.html

    • 2.2.3. result.jsp

    • 2.2.4. fileUpload.css

    • 2.1.1. 文件上传状态类(FileUploadStatus)

    • 2.1.2. 文件上传状态侦听类(FileUploadListener)

    • 2.1.3. 后台服务类(BackGroundService)

    • 2.1.4. 文件上传状态控制类(BeanControler)

  • 3. 结语


1.引言

基于浏览器的文件上传,特别是对于通过<input type="file">标签来实现上传的情况,

存在着严重的性能问题,因为用户提交了文件之后,在浏览器把文件上传到服务器的过程中,界面看上去似乎是静止的,如果是小文件还好些,如果不幸需要上传的是几兆、几十兆甚至上百兆的文件,我相信那是一种非常痛苦的体验,我们中间的很多人应该都有过此种不堪的经历。(一笑)


  现在我就针对这个问题给出一个解决方案,我们将实现一个具有监控能力的WEB上传的程序――它不仅把文件上传到服务器,而且"实时地"监视文件上传的实际过程。

解决方案的基本思路是这样的:

在介绍源代码之前,我们先来看看程序运行界面:

wKioL1PrI7TzQpS6AAB8bs-FI1M267.jpg




2. 实现代码

   实现代码想当然的有服务器端代码和客户端代码(呵呵),我们先从服务器端开始。

2.1. 服务器端代码

2.1.1. 文件上传状态类(FileUploadStatus)

   使用FileUploadStatus这个类记录文件上传状态,并将其作为服务器端与

web客户端之间通信的媒介,通过对这个类对象提供上传状态作为服务器回应发送给web客户端,

web客户端使用JavaScript获得文件上传状态。源代码如下:

/**
*本例程演示了通过Web上传文件过程中的进度显示。您可以对本例程进行任何修改和使用。
*
*如需要转载,请注明作者。
*
*作者:刘作晨
*
*/
packageliuzuochen.sample.upload;

importjava.util.*;

publicclassFileUploadStatus{
	//上传用户地址
	privateStringuploadAddr;
	//上传总量
	privatelonguploadTotalSize=0;
	//读取上传总量
	privatelongreadTotalSize=0;
	//当前上传文件号
	privateintcurrentUploadFileNum=0;
	//成功读取上传文件数
	privateintsuccessUploadFileCount=0;
	//状态
	privateStringstatus="";
	//处理起始时间
	privatelongprocessStartTime=0l;
	//处理终止时间
	privatelongprocessEndTime=0l;
	//处理执行时间
	privatelongprocessRunningTime=0l;
	//上传文件URL列表
	privateListuploadFileUrlList=newArrayList();
	//取消上传
	privatebooleancancel=false;
	//上传base目录
	privateStringbaseDir="";

	publicFileUploadStatus(){

	}

	publicStringgetBaseDir(){
		returnbaseDir;
	}

	publicvoidsetBaseDir(StringbaseDir){
		this.baseDir=baseDir;
	}

	publicbooleangetCancel(){
		returncancel;
	}

	publicvoidsetCancel(booleancancel){
		this.cancel=cancel;
	}

	publicListgetUploadFileUrlList(){
		returnuploadFileUrlList;
	}

	publicvoidsetUploadFileUrlList(ListuploadFileUrlList){
		this.uploadFileUrlList=uploadFileUrlList;
	}

	publiclonggetProcessRunningTime(){
		returnprocessRunningTime;
	}

	publicvoidsetProcessRunningTime(longprocessRunningTime){
		this.processRunningTime=processRunningTime;
	}

	publiclonggetProcessEndTime(){
		returnprocessEndTime;
	}

	publicvoidsetProcessEndTime(longprocessEndTime){
		this.processEndTime=processEndTime;
	}

	publiclonggetProcessStartTime(){
		returnprocessStartTime;
	}

	publicvoidsetProcessStartTime(longprocessStartTime){
		this.processStartTime=processStartTime;
	}

	publiclonggetReadTotalSize(){
		returnreadTotalSize;
	}

	publicvoidsetReadTotalSize(longreadTotalSize){
		this.readTotalSize=readTotalSize;
	}

	publicintgetSuccessUploadFileCount(){
		returnsuccessUploadFileCount;
	}

	publicvoidsetSuccessUploadFileCount(intsuccessUploadFileCount){
		this.successUploadFileCount=successUploadFileCount;
	}

	publicintgetCurrentUploadFileNum(){
		returncurrentUploadFileNum;
	}

	publicvoidsetCurrentUploadFileNum(intcurrentUploadFileNum){
		this.currentUploadFileNum=currentUploadFileNum;
	}

	publicStringgetStatus(){
		returnstatus;
	}

	publicvoidsetStatus(Stringstatus){
		this.status=status;
	}

	publiclonggetUploadTotalSize(){
		returnuploadTotalSize;
	}

	publicStringgetUploadAddr(){
		returnuploadAddr;
	}

	publicvoidsetUploadTotalSize(longuploadTotalSize){
		this.uploadTotalSize=uploadTotalSize;
	}

	publicvoidsetUploadAddr(StringuploadAddr){
		this.uploadAddr=uploadAddr;
	}

	publicStringtoJSon(){
		StringBufferstrJSon=newStringBuffer();
		strJSon.append("{UploadTotalSize:").append(getUploadTotalSize()).append(",")
				.append("ReadTotalSize:").append(getReadTotalSize()).append(",")
				.append("CurrentUploadFileNum:").append(getCurrentUploadFileNum())
				.append(",")
				.append("SuccessUploadFileCount:").append(getSuccessUploadFileCount())
				.append(",")
				.append("Status:'").append(getStatus()).append("',")
				.append("ProcessStartTime:").append(getProcessStartTime())
				.append(",")
				.append("ProcessEndTime:").append(getProcessEndTime()).append(",")
				.append("ProcessRunningTime:").append(getProcessRunningTime())
				.append(",")
				.append("Cancel:").append(getCancel()).append("}");
	returnstrJSon.toString();

	}
}

2.1.2. 文件上传状态侦听类(FileUploadListener)


   使用Common-FileUpload 1.2版本(20070103)。此版本提供了能够监视文件上传情况的

ProcessListener接口,使开发者通过FileUploadBase类对象的setProcessListener方法

入自己的Listener。 FileUploadListener类实现了ProcessListener,在整个文件上传过程

中,它对上传进度进行监控,并且根据上传 情况实时的更新上传状态Bean。源代码如下:

/**
*本例程演示了通过Web上传文件过程中的进度显示。您可以对本例程进行任何修改和使用。
*
*如需要转载,请注明作者。
*
*作者:刘作晨
*
*/
packageliuzuochen.sample.upload;

importorg.apache.commons.fileupload.ProgressListener;
importjavax.servlet.http.HttpServletRequest;

publicclassFileUploadListenerimplementsProgressListener{
	privateHttpServletRequestrequest=null;

	publicFileUploadListener(HttpServletRequestrequest){
		this.request=request;
	}

	/**
	*更新状态
	*/
	publicvoidupdate(longpBytesRead,longpContentLength,intpItems){
		FileUploadStatusstatusBean=BackGroundService.getStatusBean(request);
		statusBean.setUploadTotalSize(pContentLength);
		//读取完成
		if(pContentLength==-1){
			statusBean.setStatus("完成对"+pItems+"个文件的读取:读取了"+pBytesRead
					+"bytes.");
			statusBean.setReadTotalSize(pBytesRead);
			statusBean.setSuccessUploadFileCount(pItems);
			statusBean.setProcessEndTime(System.currentTimeMillis());
			statusBean.setProcessRunningTime(statusBean.getProcessEndTime());
			//读取中
		}else{
			statusBean.setStatus("当前正在处理第"+pItems+"个文件:已经读取了"+pBytesRead
					+"/"+pContentLength+"bytes.");
			statusBean.setReadTotalSize(pBytesRead);
			statusBean.setCurrentUploadFileNum(pItems);
			statusBean.setProcessRunningTime(System.currentTimeMillis());
		}
		BackGroundService.saveStatusBean(request,statusBean);
	}
}

2.1.3. 后台服务类(BackGroundService)


   BackGroundService这个Servlet类负责接收Form Post数据、回应状态轮询请求、处理取

文件上传的请求。 尽管可以把这些功能相互分离开来,但为了简单明了,还是将它们放到

Servlet中,只是由不同的方法进行分割。 源代码如下:

/**
*本例程演示了通过Web上传文件过程中的进度显示。您可以对本例程进行任何修改和使用。
*
*如需要转载,请注明作者。
*
*作者:刘作晨
*
*/
packageliuzuochen.sample.upload;

importjava.io.File;
importjava.io.IOException;
importjava.util.List;

importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;

importorg.apache.commons.fileupload.FileItem;
importorg.apache.commons.fileupload.FileUploadException;
importorg.apache.commons.fileupload.disk.DiskFileItemFactory;
importorg.apache.commons.fileupload.servlet.*;

publicclassBackGroundServiceextendsjavax.servlet.http.HttpServletimplements
		javax.servlet.Servlet{

	publicstaticfinalStringUPLOAD_DIR="/upload";
	publicstaticfinalStringDEFAULT_UPLOAD_FAILURE_URL="./result.jsp";

	publicBackGroundService(){
		super();
	}

	protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{
		doPost(request,response);
	}

	/**
	*从文件路径中取出文件名
	*/
	privateStringtakeOutFileName(StringfilePath){
		intpos=filePath.lastIndexOf(File.separator);
		if(pos>0){
			returnfilePath.substring(pos+1);
		}else{
			returnfilePath;
		}
	}

	/**
	*从request中取出FileUploadStatusBean
	*/
	publicstaticFileUploadStatusgetStatusBean(HttpServletRequestrequest){
		BeanControlerbeanCtrl=BeanControler.getInstance();
		returnbeanCtrl.getUploadStatus(request.getRemoteAddr());
	}

	/**
	*把FileUploadStatusBean保存到类控制器BeanControler
	*/
	publicstaticvoidsaveStatusBean(HttpServletRequestrequest,FileUploadStatusstatusBean){
		statusBean.setUploadAddr(request.getRemoteAddr());
		BeanControlerbeanCtrl=BeanControler.getInstance();
		beanCtrl.setUploadStatus(statusBean);
	}

	/**
	*删除已经上传文件
	*/
	privatevoiddeleteUploadedFile(HttpServletRequestrequest){
		FileUploadStatussatusBean=getStatusBean(request);
		for(inti=0;i<satusBean.getUploadFileUrlList().size();i++){
			FileuploadedFile=newFile(request.getRealPath(UPLOAD_DIR)
					+File.separator+satusBean.getUploadFileUrlList().get(i));
			uploadedFile.delete();
		}
		satusBean.getUploadFileUrlList().clear();
		satusBean.setStatus("删除上传文件");
		saveStatusBean(request,satusBean);
	}

	/**
	*上传过程中出错处理
	*/
	privatevoiduploadExceptionHandle(HttpServletRequestrequest,StringerrMsg)
			throwsServletException,IOException{
		//首先删除已经上传文件
		deleteUploadedFile(request);
		FileUploadStatussatusBean=getStatusBean(request);
		satusBean.setStatus(errMsg);
		saveStatusBean(request,satusBean);
	}

	/**
	*初始化文件上传状态Bean
	*/
	privateFileUploadStatusinitStatusBean(HttpServletRequestrequest){
		FileUploadStatussatusBean=newFileUploadStatus();
		satusBean.setStatus("正在准备处理");
		satusBean.setUploadTotalSize(request.getContentLength());
		satusBean.setProcessStartTime(System.currentTimeMillis());
		satusBean.setBaseDir(request.getContextPath()+UPLOAD_DIR);
		returnsatusBean;
	}

	/**
	*处理文件上传
	*/
	privatevoidprocessFileUpload(HttpServletRequestrequest,IOException{
		DiskFileItemFactoryfactory=newDiskFileItemFactory();
		//设置内存缓冲区,超过后写入临时文件
		factory.setSizeThreshold(10240000);
		//设置临时文件存储位置
		factory.setRepository(newFile(request.getRealPath("/upload/temp")));
		ServletFileUploadupload=newServletFileUpload(factory);
		//设置单个文件的最大上传值
		upload.setFileSizeMax(102400000);
		//设置整个request的最大值
		upload.setSizeMax(102400000);
		upload.setProgressListener(newFileUploadListener(request));
		//保存初始化后的FileUploadStatusBean
		saveStatusBean(request,initStatusBean(request));

		StringforwardURL="";
		try{
			Listitems=upload.parseRequest(request);
			//获得返回url
			for(inti=0;i<items.size();i++){
				FileItemitem=(FileItem)items.get(i);
				if(item.isFormField()){
					forwardURL=item.getString();
					break;
				}
			}
			//处理文件上传
			for(inti=0;i<items.size();i++){
				FileItemitem=(FileItem)items.get(i);

				//取消上传
				if(getStatusBean(request).getCancel()){
					deleteUploadedFile(request);
					break;
				}
				//保存文件
				elseif(!item.isFormField()&&item.getName().length()>0){
					StringfileName=takeOutFileName(item.getName());
					FileuploadedFile=newFile(
							request.getRealPath(UPLOAD_DIR)+File.separator
									+fileName);
					item.write(uploadedFile);
					//更新上传文件列表
					FileUploadStatussatusBean=getStatusBean(request);
					satusBean.getUploadFileUrlList().add(fileName);
					saveStatusBean(request,satusBean);
					Thread.sleep(500);
				}
			}

		}catch(FileUploadExceptione){
			uploadExceptionHandle(request,"上传文件时发生错误:"+e.getMessage());
		}catch(Exceptione){
			uploadExceptionHandle(request,"保存上传文件时发生错误:"+e.getMessage());
		}
		if(forwardURL.length()==0){
			forwardURL=DEFAULT_UPLOAD_FAILURE_URL;
		}
		request.getRequestDispatcher(forwardURL).forward(request,response);
	}

	/**
	*回应上传状态查询
	*/
	privatevoidresponseStatusQuery(HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException{
		response.setContentType("text/xml");
		response.setCharacterEncoding("UTF-8");
		response.setHeader("Cache-Control","no-cache");
		FileUploadStatussatusBean=getStatusBean(request);
		response.getWriter().write(satusBean.toJSon());
	}

	/**
	*处理取消文件上传
	*/
	privatevoidprocessCancelFileUpload(HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException{
		FileUploadStatussatusBean=getStatusBean(request);
		satusBean.setCancel(true);
		saveStatusBean(request,satusBean);
		responseStatusQuery(request,response);
	}

	protectedvoiddoPost(HttpServletRequestrequest,IOException{
		booleanisMultipart=ServletFileUpload.isMultipartContent(request);
		if(isMultipart){
			processFileUpload(request,response);
		}else{
			request.setCharacterEncoding("UTF-8");

			if(request.getParameter("uploadStatus")!=null){
				responseStatusQuery(request,response);
			}
			if(request.getParameter("cancelUpload")!=null){
				processCancelFileUpload(request,response);
			}

		}
	}
}

2.1.4. 文件上传状态控制类(BeanControler)


   这是一个单例类,它的功能是为客户端保存文件上传状态,这里我没有使用Session来存储

文件上传状态,因为对于AJAX这种异步调用,服务器会开启不同的Session,所以无法通过Session

保存文件上传状态。 我并不认为这种方法最好,如果有更好的方法,欢迎大家一起讨论。 源代码如下:

/**
*本例程演示了通过Web上传文件过程中的进度显示。您可以对本例程进行任何修改和使用。
*
*如需要转载,请注明作者。
*
*作者:刘作晨
*
*/
packageliuzuochen.sample.upload;

importjava.util.Vector;

publicclassBeanControler{
	privatestaticBeanControlerbeanControler=newBeanControler();
	privateVectorvector=newVector();

	privateBeanControler(){
	}

	publicstaticBeanControlergetInstance(){
		returnbeanControler;
	}

	/**
	*取得相应FileUploadStatus类对象的存储位置
	*/
	privateintindexOf(StringstrID){
		intnReturn=-1;
		for(inti=0;i<vector.size();i++){
			FileUploadStatusstatus=(FileUploadStatus)vector.elementAt(i);
			if(status.getUploadAddr().equals(strID)){
				nReturn=i;
				break;
			}
		}
		returnnReturn;
	}

	/**
	*取得相应FileUploadStatus类对象
	*/
	publicFileUploadStatusgetUploadStatus(StringstrID){
		return(FileUploadStatus)vector.elementAt(indexOf(strID));
	}

	/**
	*存储FileUploadStatus类对象
	*/
	publicvoidsetUploadStatus(FileUploadStatusstatus){
		intnIndex=indexOf(status.getUploadAddr());
		if(-1==nIndex){
			vector.add(status);
		}else{
			vector.insertElementAt(status,nIndex);
			vector.removeElementAt(nIndex+1);
		}
	}

	/**
	*删除FileUploadStatus类对象
	*/
	publicvoidremoveUploadStatus(StringstrID){
		intnIndex=indexOf(strID);
		if(-1!=nIndex)
			vector.removeElementAt(nIndex);
	}
}

2.2. 客户端代码

   客户端我们采用Prototype框架。


2.2.1. AjaxWrapper.js

   AjaxWrapper.js对Prototype进行了封装。 源代码如下:

//类工具
varClassUtils=Class.create();
ClassUtils.prototype={
_ClassUtilsName:'ClassUtils',initialize:function(){
},/**
*给类的每个方法注册一个对类对象的自我引用
*@paramreference对类对象的引用
*/
registerFuncSelfLink:function(reference){
for(varninreference){
varitem=reference[n];
if(iteminstanceofFunction)
item.$=reference;
}
}
}
//Ajax操作封装类:
//由于调用AjaxRequest类进行XMLHTTPRequest操作时,this引用(指向当前的对象)会出现了callstack问题,从而指向当前的对象。
//所以,对putRequest、callBackHandler、以及callback方法都要使用arguments.callee.$来获得正确的类对象引用
varAjaxWrapper=Class.create();
AjaxWrapper.prototype={
debug_flag:false,xml_source:'',/**
*初始化
*@paramisDebug是否显示调试信息
*/
initialize:function(isDebug){
newClassUtils().registerFuncSelfLink(this);
this.debug_flag=isDebug;
},/**
*以get的方式向server发送request
*@paramurl
*@paramparams
*@paramcallBackFunction发送成功后回调的函数或者函数名
*/
putRequest:function(url,params,callBackFunction){
varfuncHolder=arguments.callee.$;
varxmlHttp=newAjax.Request(url,{
method:'get',parameters:params,requestHeaders:['my-header-encoding','utf-8'],onFailure:function(){
alert('对不起,网络通讯失败,请重新刷新!');
},onSuccess:function(transport){
},onComplete:function(transport){
funcHolder.callBackHandler.apply(funcHolder,[transport,callBackFunction]);
}
});
},/**
*以post的方式向server发送xml请求
*@paramurl
*@parampostDataBody
*@paramcallBackFunction发送成功后回调的函数或者函数名
*/
pushRequest:function(url,postDataBody,callBackFunction){
varfuncHolder=arguments.callee.$;
varoptions={
method:'post',parameters:'',postBody:postDataBody,onFailure:function(transport){
alert('对不起,网络通讯失败,请重新发送!');
},callBackFunction]);
}
};
varxmlHttp=newAjax.Request(url,options);
},/**
*远程调用的回调处理
*@paramtransportxmlhttp的transport
*@paramcallBackFunction回调时call的方法,可以是函数也可以是函数名
*/
callBackHandler:function(transport,callBackFunction){
varfuncHolder=arguments.callee.$;
if(transport.status!=200){
alert("获得回应失败,请求状态:"+transport.status);
}
else{
funcHolder.xml_source=transport.responseText;
if(funcHolder.debug_flag)
alert('callcallbackfunction');
if(typeof(callBackFunction)=='function'){
if(funcHolder.debug_flag){
alert('invokecallbackFunc');
}
callBackFunction(transport.responseText);
}
else{
if(funcHolder.debug_flag){
alert('evalFunccallbackFunc');
}
newexecute().evalFunc(callBackFunction,transport.responseText);
}
if(funcHolder.debug_flag)
alert('endcallbackfunction');
}
},//显示xml信息
showXMLResponse:function(){
varfuncHolder=arguments.callee.$;
alert(funcHolder.xml_source);
}
}
varXMLDomForAjax=Class.create();
XMLDomForAjax.prototype={
isDebug:false,//dom节点类型常量
ELEMENT_NODE:1,ATTRIBUTE_NODE:2,TEXT_NODE:3,CDATA_SECTION_NODE:4,ENTITY_REFERENCE_NODE:5,ENTITY_NODE:6,PROCESSING_INSTRUCTION_NODE:7,COMMENT_NODE:8,DOCUMENT_NODE:9,DOCUMENT_TYPE_NODE:10,DOCUMENT_FRAGMENT_NODE:11,NOTATION_NODE:12,initialize:function(isDebug){
newClassUtils().registerFuncSelfLink(this);
this.isDebug=isDebug;
},/**
*建立跨平台的dom解析器
*@paramxmlxml字符串
*@returndom解析器
*/
createDomParser:function(xml){
//codeforIE
if(window.ActiveXObject){
vardoc=newActiveXObject("Microsoft.XMLDOM");
doc.async="false";
doc.loadXML(xml);
}
//codeforMozilla,Firefox,Opera,etc.
else{
varparser=newDOMParser();
vardoc=parser.parseFromString(xml,"text/xml");
}
returndoc;
},/**
*反向序列化xml到javascriptBean
*@paramxmlxml字符串
*@returnjavascriptBean
*/
deserializedBeanFromXML:function(xml){
varfuncHolder=arguments.callee.$;
vardoc=funcHolder.createDomParser(xml);
//documentElement总表示文档的root
varobjDomTree=doc.documentElement;
varobj=newObject();
for(vari=0;i<objDomTree.childNodes.length;i++){
//获得节点
varnode=objDomTree.childNodes[i];
//取出其中的field元素进行处理
if((node.nodeType==funcHolder.ELEMENT_NODE)&&(node.tagName=='field')){
varnodeText=funcHolder.getNodeText(node);
if(funcHolder.isDebug){
alert(node.getAttribute('name')+'type:'+node.getAttribute('type')+'text:'+nodeText);
}
varobjFieldValue=null;
//如果为列表
if(node.getAttribute('type')=='java.util.List'){
if(objFieldValue&&typeof(objFieldValue)=='Array'){
if(nodeText.length>0){
objFieldValue[objFieldValue.length]=nodeText;
}
}
else{
objFieldValue=newArray();
}
}
elseif(node.getAttribute('type')=='long'
||node.getAttribute('type')=='java.lang.Long'
||node.getAttribute('type')=='int'
||node.getAttribute('type')=='java.lang.Integer'){
objFieldValue=parseInt(nodeText);
}
elseif(node.getAttribute('type')=='double'
||node.getAttribute('type')=='float'
||node.getAttribute('type')=='java.lang.Double'
||node.getAttribute('type')=='java.lang.Float'){
objFieldValue=parseFloat(nodeText);
}
elseif(node.getAttribute('type')=='java.lang.String'){
objFieldValue=nodeText;
}
else{
objFieldValue=nodeText;
}
//赋值给对象
obj[node.getAttribute('name')]=objFieldValue;
if(funcHolder.isDebug){
alert(eval('obj.'+node.getAttribute('name')));
}
}
elseif(node.nodeType==funcHolder.TEXT_NODE){
if(funcHolder.isDebug){
//alert('TEXT_NODE');
}
}
elseif(node.nodeType==funcHolder.CDATA_SECTION_NODE){
if(funcHolder.isDebug){
//alert('CDATA_SECTION_NODE');
}
}
}
returnobj;
},/**
*获得dom节点的text
*/
getNodeText:function(node){
varfuncHolder=arguments.callee.$;
//isthisatextorCDatanode?
if(node.nodeType==funcHolder.TEXT_NODE||node.nodeType==funcHolder.CDATA_SECTION_NODE){
returnnode.data;
}
vari;
varreturnValue=[];
for(i=0;i<node.childNodes.length;i++){
//采用递归算法
returnValue.push(funcHolder.getNodeText(node.childNodes[i]));
}
returnreturnValue.join('');
}
}
//委托者类
varDispatcher=Class.create();
Dispatcher.prototype={
name:'Dispatcher',//对class中的每个function都赋值一个值为this的$属性
initialize:function(){
newClassUtils().registerFuncSelfLink(this);
},/**
*委托调用
*@paramcaller调用者,func的拥有者
*@paramfunc如果是function对象,则使用Dispatcher对象自己的name作为参数;否则直接调用func
*/
dispatch:function(caller,func){
if(funcinstanceofFunction){
varfuncArguments=newArray();
funcArguments[0]=arguments.callee.$.name;
func.apply(caller,funcArguments);
}
else{
eval(func);
}
}
}
//祈祷者类
varInvoker=Class.create();
Invoker.prototype={
name:'Invoker',invoke:function(showMsg){
alert(showMsg+"――this.name="+this.name);
}
}

2.2.2. fileUpload.html

   fileUpload.html是文件上传界面。 源代码如下:

<html>
<html>
<head>
<Metahttp-equiv="Content-Type"content="text/html;charset=GBK">
<scripttype="text/javascript"src="./javascript/prototype.js"></script>
<scripttype="text/javascript"src="./javascript/AjaxWrapper.js"></script>
<linkhref="./css/fileUpload.css"type="text/css"rel="stylesheet"/>
<title>文件上传</title>
</head>
<body>
<divid="controlPanel">
<divid="readme">测试说明:最大上传量:100M,单个文件最大长度:100M</div>
<divid="uploadFileUrl"></div>
<formid="fileUploadForm"name="fileUploadForm"action="./BackGroundService.action"
enctype="multipart/form-data"method="post">
<inputtype="file"name="file"id="file"size="40"/><br>
<inputtype="file"name="file"id="file"size="40"/><br>
<inputtype="file"name="file"id="file"size="40"/><br>
<inputtype="submit"name="uploadButton"id="uploadButton"value="开始上传"/>
<inputtype="button"name="cancelUploadButton"id="cancelUploadButton"value="取消上传"/><br>
</form>
<divid="progressBar">
<divid="theMeter">
<divid="progressBarText"></div>
<divid="totalProgressBarBox">
<divid="totalProgressBarBoxContent"></div>
</div>
</div>
<divid="progressStatusText"></div>
</div>
</div>
<script>
Element.hide('progressBar');
Event.observe('fileUploadForm','submit',startProgress,false);
Event.observe('cancelUploadButton','click',cancelProgress,false);

//刷新上传状态
functionrefreshUploadStatus(){
varajaxW=newAjaxWrapper(false);
ajaxW.putRequest(
'./BackGroundService.action','uploadStatus=',function(responseText){
eval("uploadInfo="+responseText);
varprogressPercent=Math.ceil(
(uploadInfo.ReadTotalSize)/uploadInfo.UploadTotalSize*100);

$('progressBarText').innerHTML='上传处理进度:'+progressPercent+'%['+
(uploadInfo.ReadTotalSize)+'/'+uploadInfo.UploadTotalSize+'bytes]'+
'正在处理第'+uploadInfo.CurrentUploadFileNum+'个文件'+
'耗时:'+(uploadInfo.ProcessRunningTime-uploadInfo.ProcessStartTime)+'ms';
$('progressStatusText').innerHTML='反馈状态:'+uploadInfo.Status;
$('totalProgressBarBoxContent').style.width=parseInt(progressPercent*3.5)+'px';
}
);
}
//上传处理
functionstartProgress(){
Element.show('progressBar');
$('progressBarText').innerHTML='上传处理进度:0%';
$('progressStatusText').innerHTML='反馈状态:';
$('uploadButton').disabled=true;
varperiodicalExe=newPeriodicalExecuter(refreshUploadStatus,0.5);
returntrue;
}
//取消上传处理
functioncancelProgress(){
$('cancelUploadButton').disabled=true;
varajaxW=newAjaxWrapper(false);
ajaxW.putRequest(
'./BackGroundService.action','cancelUpload=true',//因为form的提交,这可能不会执行
function(responseText){
eval("uploadInfo="+responseText);
$('progressStatusText').innerHTML='反馈状态:'+uploadInfo.status;
if(msgInfo.cancel=='true'){
alert('删除成功!');
window.location.reload();
};
}
);
}
</script>
</body>
</html>

2.2.3. result.jsp


   result.jsp是文件上传结果显示界面。 源代码如下:

<%@pagelanguage="java"
contentType="text/html;charset=GBK"
pageEncoding="GBK"%>
<%@pageimport="liuzuochen.sample.upload.*"%>
<!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.01Transitional//EN">
<html>
<head>
<Metahttp-equiv="Content-Type"content="text/html;charset=GBK">
<linkhref="./css/fileUpload.css"type="text/css"rel="stylesheet"/>
<title>文件上传结果</title>
</head>
<body>
<divid="resultPanel">
<div><span>上传文件列表:</span></div>
<%
FileUploadStatusfUploadStatus=BackGroundService.getStatusBean(request);
for(inti=0;i<fUploadStatus.getUploadFileUrlList().size();i++){
StringfileName=(String)fUploadStatus.getUploadFileUrlList().get(i);
Stringurl=fUploadStatus.getBaseDir()+"/"+fileName;
%>
<div><ahref="<%=url%>"_fcksavedurl="<%=url%>"_fcksavedurl="<%=url%>"
_fcksavedurl="<%=url%>"><%=fileName%></a></div>
<%
}
if(fUploadStatus.getStatus().indexOf("错误")>=0){
%>
<divid='errorArea'><span>错误信息:<%=fUploadStatus.getStatus()%></span></div>
<%
}
elseif(fUploadStatus.getCancel()){
%>
<divid='normalMessageArea'><span>由于用户取消上传,所以已经上传文件均被删除</span></div>
<%
}
BeanControler.getInstance().removeUploadStatus(request.getRemoteAddr());
%>
</div>
</body>
</html>

2.2.4. fileUpload.css


   fileUpload.css是样式文件。 源代码如下:

body{
color:#000;
background-color:white;
font:15pxGeorgia,"LucidaGrande",Arial,sans-serif;
letter-spacing:0.01em;
margin:15px;
}
#controlPanel,#resultPanel{
width:700px;
margin:20pxauto;
padding:25px;
border:3pxsolidgray;
-moz-border-radius:10px;
background:#f8f8f8;
}
#errorArea{
width:400px;
margin:20pxauto;
padding:25px;
border:3pxsolidgray;
-moz-border-radius:10px;
background:red;
}
#normalMessageArea{
width:400px;
margin:20pxauto;
padding:25px;
border:3pxsolidgray;
-moz-border-radius:10px;
background:yellow;
}
#progressBar{padding-top:5px;}
#totalProgressBarBox{
width:350px;
height:20px;
border:1pxinset;
background:#eee;
}
#totalProgressBarBoxContent{
width:0;
height:20px;
border-right:1pxsolid#444;
background:#9ACB34;
}

2.3. 配置文件


   把如下代码加入web.xml中完成Servlet的配置。

<servlet>
<br><description>
<br></description>
<br><display-name>
<br>BackGroundService</display-name>
<br><servlet-name>BackGroundService</servlet-name>
<br><servlet-class>
<br>liuzuochen.sample.upload.BackGroundService</servlet-class>
<br></servlet>
<br><servlet-mapping>
<servlet-name>BackGroundService</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>

3. 结语

   整个程序到这里就介绍完了,希望它多少能为您的工作或学习带来点儿帮助。

猜你在找的Ajax相关文章