`

ExtJS 多文件上传,单文件上传组件

 
阅读更多
这次一共开发了三款文件上传组件,基于swfupload实现多文件上传,带有上传进度,实时显示上传进度等信息,基于swfupload实现单文件上传组件,继承了ext的twintriggerfield,第三个是基于原生的文件上传,继承twintriggerfield实现文件上传,随表单一起提交,当然每个人的需求不同,大家可以在此基础上再进行修改,说明一下,多文件上传组件参考了dogdisk的文件上传;

多文件上传:
[img]
http://dl.iteye.com/upload/attachment/0070/7869/066ba281-d50f-325a-8b39-5ff5bd76488d.jpg
[/img]
/**
 * Swf文件上传
 * @class Ext.ux.ISwfUploadPanel
 * @extends Ext.Window
 */
Ext.ux.SwfUploadPanel = Ext.extend(Ext.Window,{
	uploadUrl : 'uploadFiles.action',//文件上传到服务器上的URL
	postParams : {},//随文件上传提交的参数
	flashUrl : 'js/ext/resources/swfupload.swf',//flash文件地址
	filePostName : 'uploadFile.upload',
	fileSize : '5000 MB',//允许上传文件的最大的大小
	fileTypes : '*.*',//允许上传文件的类型
	fileTypesDescription : '所有文件',//允许上传文件类型说明
	allowNumber : 0,//0表示不限制文件个数
	btnOKHandler : Ext.emptyFn,//点击确定按钮的动作
	btnCancelHandler : Ext.emptyFn,//点击取消按钮的动作
	
	title : '文件上传',
	iconCls : '',
	layout : 'fit',
	width : 550,
	height : 350,
	progressInfo : {
		filesTotal : 0,//总文件数量
		filesUploaded : 0,//上传了的文件的数量
		bytesTotal : 0,//总文件大小
		bytesUploaded : 0,//上传了的文件大小
		currentCompleteBytes : 0,//当前已完成文件的大小
		lastBytes : 0,
		lastElapsed : 1,
		lastUpdate : null,
		timeElapsed : 1
	},
	initComponent : function(){
		
		Ext.ux.SwfUploadPanel.superclass.initComponent.call(this);
		
		this.store = new Ext.data.SimpleStore({
			fields : ['fileId','fileName','fileType','fileSize','fileState','fileSrc'],
			pruneModifiedRecords : true,
			listeners : {
				scope : this,
				'add' : this.doControlBtns,
				'remove' : this.doControlBtns
			}
		});
		
		//数据表顶部工具条
		this.topBar = new Ext.Toolbar({
			defaults : {
				scope : this
			}
		});
		
		//数据表底部工具条
		this.bottomBar = new Ext.Toolbar({
			defaultType : 'displayfield',
			items : ['时间:',{
				ref : 'time',
				value : '00:00:00'
			},'-','速度:',{
				ref : 'speed',
				value : '0 KB/s'
			},'-','状态:',{
				ref : 'state',
				value : '0 KB / 0KB'
			},'->',{
				xtype : 'progress',
				ref : 'progressBar',
				text : '0 %',
				width : 180
			}
//			{
//				xtype : 'panel',
//				layout : 'form',
//				bodyStyle : 'background:transparent;border:none;',
//				cls : 'x-toolbar-ct',
//				items : [{
//					xtype : 'textfield'
//				},{
//					xtype : 'combo'
//				}]
//			}
			]
		});
		
		this.cm = new Ext.grid.ColumnModel({
			defaults : {
				sortable : true
			},
			columns : [new Ext.grid.RowNumberer({width : 22}),{
				header : '文件名称',
				dataIndex : 'fileName',
				width : 150
			},{
				header : '文件类型',
				dataIndex : 'fileType',
				width : 60
			},{
				header : '文件大小',
				dataIndex : 'fileSize',
				width : 80,
				renderer : this.renderFileSize
			},{
				header : '进度',
				dataIndex : '',
				renderer : this.renderProgressBar
			},{
				header : '状态',
				dataIndex : 'fileState',
				width : 70,
				renderer : this.renderFileState
			},{
				header : '',
				dataIndex : '',
				width : 30,
				renderer : function(value,metadata,record){
					switch(record.data.fileState){
						case SWFUpload.FILE_STATUS.COMPLETE : 
							return '<div class="oa-good" style="width:20px;height:20px;">&nbsp;</div>';
						case SWFUpload.FILE_STATUS.IN_PROGRESS :
							return '<div class="oa-loading" style="width:16px;height:16px;">&nbsp;</div>';
						case SWFUpload.FILE_STATUS.CANCELLED :
							return '<div class="oa-no" style="width:14px;height:14px;">&nbsp;</div>';
						case SWFUpload.FILE_STATUS.ERROR :
							return '<div class="oa-bad" style="width:16px;height:16px;">&nbsp;</div>';
					}
				}
			}]
		});
		
		//数据表
		this.grid = new Ext.grid.GridPanel({
			tbar : this.topBar,
			bbar : this.bottomBar,
			cm : this.cm,
			store : this.store,
			enableColumnHide : false,
			viewConfig : {
				forceFit : true,
				emptyText : '<div style="text-align:center; padding:20px">请选择要上传的文件</div>'
			},
			listeners : {
				scope : this,
				'render' : this.initSwfSettings
			}
		});
		
		this.add(this.grid);
		if(Ext.isEmpty(this.buttons)){
			this.addButton({text : '确定',scope : this},this.doConfirmUploadPanel);
			this.addButton({text : '取消',scope : this},this.doCloseUploadPanel);
		}
		
		this.on('show',this.initProgressInfo,this);
	},
	
	//点击窗体上的取消按钮
	doCloseUploadPanel : function(){
		this[this.closeAction]();
		this.btnCancelHandler.call(this);
	},
	
	//点击窗体上的确定按钮
	doConfirmUploadPanel : function(){
		this[this.closeAction]();
		this.btnOKHandler.call(this);
	},
	
	//重写window的doClose方法
	doClose : function(){
		if(!this.isDestroyed){
            if(this.fireEvent('beforedestroy', this) !== false){
                this.destroying = true;
                if(this.rendered){
		            this.hide();
		            this.clearAnchor();
		            this.grid.getView().destroy();
		            Ext.destroy(this.focusEl);
		            Ext.destroy(this.resizer);
		            Ext.destroy(this.dd);
		            Ext.destroy(this.proxy);
		            Ext.destroy(this.mask);
		            
		        }
                
                if(this.ownerCt && this.ownerCt.remove){
                    this.ownerCt.remove(this, false);
                }
                if(this.rendered){
                    this.el.remove();
                    if(this.actionMode == 'container' || this.removeMode == 'container'){
                        this.container.remove();
                    }
                }
                // Stop any buffered tasks
                if(this.focusTask && this.focusTask.cancel){
                    this.focusTask.cancel();
                }
                this.onDestroy();
                Ext.ComponentMgr.unregister(this);
                this.fireEvent('destroy', this);
                this.purgeListeners();
                this.destroying = false;
                this.isDestroyed = true;
            }
        }
        return;
		
		Ext.get(this.id).remove();return;
		Ext.getCmp(this.id).close();
	},
	
	//第一步:初始化flash上传组件设置
	initSwfSettings : function(){
		this.topBar.add({
			text : '添加',
			ref : 'addFile',
			iconCls : 'oa-add'
		},'-',{
			text : '删除',
			ref : 'removeFile',
			iconCls : 'oa-delete',
			handler : this.doRemove
		},'-',{
			text : '上传',
			ref : 'uploadFile',
			state : 'upload',
			iconCls : 'oa-img-upload',
			disabled : true,
			handler : this.doUpload
		});
		this.topBar.doLayout();
		var em = this.grid.getTopToolbar().items.first().el.child('em');;
        var placeHolderId = Ext.id();
        em.setStyle({
            position: 'relative',
            display: 'block'
        });
        em.createChild({
            tag: 'div',
            id: placeHolderId
        });
		this.swfupload = new SWFUpload({
			upload_url : this.uploadUrl,
			post_params : Ext.isEmpty(this.postParams) ? {}:this.postParams,
			flash_url : this.flashUrl, 
			file_post_name : this.filePostName,
			file_size_limit : this.fileSize,
			file_types : this.fileTypes,
			file_types_description : this.fileTypesDescription,
			file_upload_limit : this.allowNumber,//允许同时上传文件的数量,默认值为0,即不限制。当文件队列中的文件数,正在上传的文件以及已经上传成功的文件数只和超过了该值后,便不在允许添加文件
            file_queue_limit : this.allowNumber,//允许队列存在的文件数量,默认值为0,即不限制。当文件队列中的文件数超过该值便不再允许添加文件
//			use_query_string:true,
			debug : false,
			button_width : '48',
			button_height : '20',
			button_placeholder_id : placeHolderId,
			button_window_mode : SWFUpload.WINDOW_MODE.TRANSPARENT,
			button_cursor : SWFUpload.CURSOR.HAND,
			button_disabled : false,//按钮是否禁用,默认值为false
			//button_action : //设置Flash Button点击以后的动作,默认值为SWFUpload.BUTTON_ACTION.SELECT_FILES(多文件上传)
			//requeue_on_error, //是否将上传失败的的文件重新添加到上传队列的顶端,默认值为true。当文件上传失败或者停止上传触发uploadError事件,是否将上传失败的的文件重新添加到上传队列的顶端,当然调用cancelUpload方法触发uploadError事件,不会将文件重新添加到上传队列中,而是会丢弃
			custom_settings : {
				scope_handler : this
			},
			swfupload_loaded_handler : this.onFlashCompleteInit,
			file_dialog_start_handler : this.onBeforeFileWindowOpen,
			
			file_queued_handler : this.onAddFileToQueue,
			file_queue_error_handler : this.onAddFileToQueueError,
			file_dialog_complete_handler : this.onAddFileToQueueComplete,
			
			upload_start_handler : this.doUpload,
			upload_progress_handler : this.doUploadProgress,
			upload_error_handler : this.doUploadError,
			upload_success_handler : this.doUploadSuccess,
			upload_complete_handler : this.doUploadComplete
		});
		this.swfupload.uploadStopped = false;
		Ext.get(this.swfupload.movieName).setStyle({
            position: 'absolute', 
            top: '-2px',
            left: '-2px'
        });
	},
	
	//初始化进度信息
	initProgressInfo : function(){
		this.progressInfo = {
			filesTotal : 0,//总文件数量
			filesUploaded : 0,//上传了的文件的数量
			bytesTotal : 0,//总文件大小
			bytesUploaded : 0,//上传了的文件大小
			currentCompleteBytes : 0,//当前已完成文件的大小
			lastBytes : 0,
			lastElapsed : 1,
			lastUpdate : null,
			timeElapsed : 1
		}
	},
	
	/**flash文件初始化完成之后调用
	 */
	onFlashCompleteInit : Ext.emptyFn,
	
	/**打开浏览窗口之前调用
	 */
	onBeforeFileWindowOpen : Ext.emptyFn,
	
	//第二步:添加文件到数据表中
	onAddFileToQueue : function(file){
		var thiz = this.customSettings.scope_handler;
        thiz.grid.store.add(new thiz.grid.store.recordType({
            fileId : file.id,
			fileName : file.name,
			fileSize : file.size,
			fileType : file.type,
			fileState : file.filestatus
        }));
        
        thiz.progressInfo.filesTotal += 1;//文件总数
		thiz.progressInfo.bytesTotal += file.size;//文件总大小
		
		thiz.doUpdateProgressInfo();//添加了文件后根据进度信息进新一次进度显示
	},
	
	//添加一个文件到队列中出现错误
	onAddFileToQueueError : function(file, errorCode, message){
		var thiz = this.customSettings.scope_handler;
		var errorMsg = '';
		switch(errorCode){
			case SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED :
				errorMsg = String.format('尝试添加太多的文件进入队列,只可以添加<b>{0}</b>个文件',message);break;
			case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT :
				errorMsg = String.format('<b>{0}</b>大小超出限制,只可以添加不超过<b>{1}</b>的文件',file.name,thiz.fileSize);break;
			case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE :
				errorMsg = String.format('<b>{0}</b>是0字节文件,不能上传0字节的文件',file.name);break;
			case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE :
				errorMsg = String.format('<b>{0}</b>是无效文件类型',file.name);break;
			default : 
				errorMsg = '添加文件时出现未知错误';
		}
		
		Ext.Msg.show({
			title : '提示',
		    msg : errorMsg,
		    buttons: Ext.Msg.OK,
		    fn: Ext.emptyFn,
		    icon: Ext.MessageBox.INFO
		});
	},
	
	//添加文件到数据表动作完成
	onAddFileToQueueComplete : function(selectedFilesCount, queuedFilesCount){
		//alert("selectedFilesCount:" + selectedFilesCount + "  queuedFilesCount:" + queuedFilesCount );
	},
	
	//第三步:点击上传按钮,开始上传
	doUpload : function(){
		if (this.swfupload) {
			var btn = this.topBar.uploadFile;//取得按钮对象
			if(btn && btn.state == 'upload'){
				this.swfupload.uploadStopped = false;
				var post_params = this.swfupload.settings.post_params;
				this.swfupload.setPostParams(post_params);
				this.swfupload.startUpload();
				
				btn.setText('停止');
				btn.state = 'pause'
				btn.setIconClass('oa-pause');
			}else{
				this.swfupload.uploadStopped = true;
				this.swfupload.stopUpload();
				btn.setText('上传');
				btn.state = 'upload',
				btn.setIconClass('oa-img-upload');
			}
			this.doControlBtns(false);
		}
	},
	
	//从数据表中移除文件
	doRemove : function(){
		var records = this.grid.getSelected(true);//取得选定的所有的记录
		if(records.length<1){
			Ext.uxMsg.tip(Ext.uxMsg.INFO,'请选择要移除的文件');return;
		}
		Ext.each(records,function(record){
			if(record.data.fileState != SWFUpload.FILE_STATUS.IN_PROGRESS /*&& record.data.fileState != SWFUpload.FILE_STATUS.QUEUED.COMPLETE*/){
				this.swfupload.cancelUpload(record.data.fileId);//此句一定要加上,它会触会doUploadError事件
				if(record.data.fileState != SWFUpload.FILE_STATUS.CANCELLED){
					
					
					this.progressInfo.filesTotal -= 1;
					this.progressInfo.bytesTotal -= record.data.fileSize;
					switch(record.data.fileState){
						case SWFUpload.FILE_STATUS.CANCELLED:
							this.progressInfo.bytesUploaded -= this.progressInfo.currentCompleteBytes;break;
						case SWFUpload.FILE_STATUS.ERROR :
						case SWFUpload.FILE_STATUS.COMPLETE:
							this.progressInfo.bytesUploaded -= record.data.fileSize;break;
					}
					
					//record.set('fileState',SWFUpload.FILE_STATUS.CANCELLED);
					//record.commit();
					this.store.remove(record);
					this.doUpdateProgressInfo();
				}
			}
		},this);
		this.grid.getView().refresh();
	},
	
	/**上传过程中进度
	 * @param {} file 文件对象
	 * @param {} completeBytes 已经上传的字节数(当前文件已上传了的大小)
	 * @param {} bytesTotal 总共要上传的字节数(当前文件总大小)
	 */
	doUploadProgress : function(file, completeBytes, bytesTotal){
		//处理数据表里列进度条
		var thiz = this.customSettings.scope_handler;
//		try{
			var percent = Math.ceil((completeBytes / bytesTotal) * 100);
			Ext.getDom('progressBar_' + file.id).style.width = percent + "%";
			Ext.getDom('progressText_' + file.id).innerHTML = percent + " %";
			var record = thiz.store.getById(Ext.getDom('fileId_' + file.id).parentNode.id);
			record.set('fileState',file.filestatus);
			
			//生成基本进度相关信息
			var bytes_added = completeBytes - thiz.progressInfo.currentCompleteBytes;
			thiz.progressInfo.bytesUploaded += Math.abs(bytes_added < 0 ? 0 : bytes_added);
			thiz.progressInfo.currentCompleteBytes = completeBytes;
			
			if (thiz.progressInfo.lastUpdate) {
				thiz.progressInfo.lastElapsed = thiz.progressInfo.lastUpdate.getElapsed();
				thiz.progressInfo.timeElapsed += thiz.progressInfo.lastElapsed;
			}
			thiz.progressInfo.lastBytes = bytes_added;
			thiz.progressInfo.lastUpdate = new Date();
			
			thiz.doUpdateProgressInfo();//更新底部工具条上进度信息
			
//		}catch(e){
//		
//		}
	},
	
	//更新上传进度信息
	doUpdateProgressInfo : function(){
		var pInfo = {};
		pInfo.filesUploaded = String.leftPad(this.progressInfo.filesUploaded, 3, '&nbsp;');
		pInfo.filesTotal = this.progressInfo.filesTotal;
		
		pInfo.bytesUploaded = String.leftPad(Ext.util.Format.fileSize(this.progressInfo.bytesUploaded), 6, '&#160;');
		pInfo.bytesTotal = Ext.util.Format.fileSize(this.progressInfo.bytesTotal);
		
		pInfo.timeElapsed = this.formatTime(this.progressInfo.timeElapsed);
		pInfo.speedAverage = Ext.util.Format.fileSize(Math.ceil(1000 * this.progressInfo.bytesUploaded / this.progressInfo.timeElapsed)) + '/s';
		pInfo.timeLeft = this.formatTime((this.progressInfo.bytesUploaded === 0) ? 0 : this.progressInfo.timeElapsed * (this.progressInfo.bytesTotal - this.progressInfo.bytesUploaded) / this.progressInfo.bytesUploaded);
		var caleSpeed = 1000 * this.progressInfo.lastBytes / this.progressInfo.lastElapsed;
		pInfo.speedLast = Ext.util.Format.fileSize(caleSpeed < 0 ? 0:caleSpeed) + '/s';
		
		//时间信息
		this.bottomBar.time.setValue(pInfo.timeLeft);
		//速度信息
		this.bottomBar.speed.setValue(pInfo.speedAverage);
		//状态信息
		this.bottomBar.state.setValue(pInfo.bytesUploaded + '&nbsp;/&nbsp;' + pInfo.bytesTotal);
		//总进度条信息
		var p = (this.progressInfo.bytesUploaded / this.progressInfo.bytesTotal) || 0;
		this.bottomBar.progressBar.updateProgress(p, p>=1?'完成&nbsp;100 %':String.format('{0} %',Math.ceil(p * 100)));
	},
	
	//当一个文件上传失败后调用此方法,cancelUpload方法调用后也会触发此事件
	doUploadError : function(file, errorCode, message){
		var thiz = this.customSettings.scope_handler;
		var tipMsg = null;
		try{
			var record = thiz.store.getById(Ext.getDom('fileId_' + file.id).parentNode.id);
			record.set('fileState',file.filestatus);
			switch(errorCode){
				case SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED :
					tipMsg = String.format('<div id="fileId_{0}"/><font color="red">{1}上传失败,上传被终止</font',record.data.fileId,record.data.fileName);
//					alert(thiz.progressInfo.bytesUploaded +'\t' + thiz.progressInfo.lastBytes + '\t' + thiz.progressInfo.currentCompleteBytes);
					thiz.progressInfo.bytesUploaded -= thiz.progressInfo.currentCompleteBytes;
					break;
				case SWFUpload.UPLOAD_ERROR.MISSING_UPLOAD_URL :
					tipMsg = String.format('<div id="fileId_{0}"/><font color="red">{1}上传失败,丢失URL</font>',record.data.fileId,record.data.fileName);break;
				case SWFUpload.UPLOAD_ERROR.IO_ERROR :
					tipMsg = String.format('<div id="fileId_{0}"/><font color="red">{1}上传失败,IO异常</font>',record.data.fileId,record.data.fileName);break;
				case SWFUpload.UPLOAD_ERROR.SECURITY_ERROR :
					tipMsg = String.format('<div id="fileId_{0}"/><font color="red">{1}上传失败,安全错误</font>',record.data.fileId,record.data.fileName);break;
				case SWFUpload.UPLOAD_ERROR.UPLOAD_LIMIT_EXCEEDED :
					tipMsg = String.format('<div id="fileId_{0}"/><font color="red">{1}上传失败,大小限制异常</font>',record.data.fileId,record.data.fileName);break;
				case SWFUpload.UPLOAD_ERROR.UPLOAD_FAILED :
					tipMsg = String.format('<div id="fileId_{0}"/><font color="red">{1}上传失败,上传异常</font>',record.data.fileId,record.data.fileName);break;
				case SWFUpload.UPLOAD_ERROR.SPECIFIED_FILE_ID_NOT_FOUND :
					tipMsg = String.format('<div id="fileId_{0}"/><font color="red">{1}上传失败,文件编号丢失</font>',record.data.fileId,record.data.fileName);break;
				case SWFUpload.UPLOAD_ERROR.FILE_VALIDATION_FAILED :
					tipMsg = String.format('<div id="fileId_{0}"/><font color="red">{1}上传失败,验证失败</font>',record.data.fileId,record.data.fileName);break;
				case SWFUpload.UPLOAD_ERROR.FILE_CANCELLED:
					tipMsg = String.format('<div id="fileId_{0}"/><font color="red">{1}上传失败,文件取消</font>',record.data.fileId,record.data.fileName);
					break;
			}
		}catch(e){
			
		}finally{
			thiz.doUpdateProgressInfo();
		}
		
		if(!Ext.isEmpty(tipMsg)){
			Ext.Msg.show({
				title : '提示',
			    msg : tipMsg,
			    width : 320,
			    buttons: Ext.Msg.OK,
			    fn: Ext.emptyFn,
			    icon: Ext.MessageBox.INFO
			});
		}
//		alert('onUploadError,errorCode:' + errorCode + ",message:" + message  + ",file.filestatus:" + file.filestatus);
	},
	
	/**当一个文件上传成功后调用些方法
	 * @param {} file 文件对象
	 * @param {} responseText 服务端响应的信息
	 * @param {} isResponsed 是否有服务端响应信息
	 */
	doUploadSuccess : function(file, responseText,isResponsed){
		var thiz = this.customSettings.scope_handler;
		try{
			var record = thiz.store.getById(Ext.getDom('fileId_' + file.id).parentNode.id);
			if(Ext.util.JSON.decode(responseText).success){
				thiz.progressInfo.filesUploaded += 1;
				thiz.doUpdateProgressInfo();
				record.set('fileState',file.filestatus);
				record.commit();
			}
		}catch(e){
			record.set('fileState',SWFUpload.FILE_STATUS.ERROR);
			record.commit();
		}
		thiz.doUpdateProgressInfo();
	},
	
	//当一个文件上传完成后如果队列中还有待上传的文件再次调用上传方法
	doUploadComplete : function(file){
		if (this.getStats().files_queued > 0 && this.uploadStopped == false) {
			this.startUpload();
		}else if(this.getStats().files_queued == 0){
			var thiz = this.customSettings.scope_handler;
			var btn = thiz.topBar.uploadFile;
			btn.setText('上传');
			btn.state = 'upload',
			btn.setIconClass('oa-img-upload');
			thiz.doControlBtns(false);
		}
	},
	
	//数据表里进度条列渲染函数
	renderProgressBar : function(v, cellmeta, record){
		var returnValue = '';
		switch(record.data.fileState){
			case SWFUpload.FILE_STATUS.COMPLETE:
				if(Ext.isIE){
					returnValue = 
						'<div class="x-progress-wrap" style="height: 18px">' +
							'<div class="x-progress-inner">' +
								'<div style="width: 100%;" class="x-progress-bar x-progress-text">' + '100 %'
								'</div>' +
							'</div>' +
						'</div>';
				}else{
					returnValue = 
						'<div class="x-progress-wrap" style="height: 18px">' +
							'<div class="x-progress-inner">' +
								'<div id="progressBar_' + record.data.fileId + '" style="width: 100%;" class="x-progress-bar">' +
								'</div>' +
								'<div id="progressText_' + record.data.fileId + '" style="width: 100%;" class="x-progress-text x-progress-text-back" />100 %</div>'
							'</div>' +
						'</div>';
				}
				break;
			default : 
				returnValue = 
					'<div class="x-progress-wrap" style="height: 18px">' +
						'<div class="x-progress-inner">' +
							'<div id="progressBar_' + record.data.fileId + '" style="width: 0%;" class="x-progress-bar">' +
							'</div>' +
							'<div id="progressText_' + record.data.fileId + '" style="width: 100%;" class="x-progress-text x-progress-text-back" />0 %</div>'
						'</div>' +
					'</div>';
				break;
		}
		return returnValue;
	},
	
	//数据表文件大小渲染函数
	renderFileSize : function(v,meta,record){
		return '<div id="fileSize_' + record.data.fileId + '">' + Ext.util.Format.fileSize(v) + '</div>';
	},
	
	//数据表里文件状态渲染函数
	renderFileState : function(v,meta,record){
		var returnValue = '';
		switch(v){
			case SWFUpload.FILE_STATUS.QUEUED:
				returnValue = String.format('<span id="{0}"><div id="fileId_{1}"/>等待上传</span>',record.id,record.data.fileId);break;
			case SWFUpload.FILE_STATUS.CANCELLED:
				returnValue = String.format('<span id="{0}"><div id="fileId_{1}"/>取消上传</span>',record.id,record.data.fileId);break;
			case SWFUpload.FILE_STATUS.COMPLETE:
				returnValue = String.format('<span id="{0}"><div id="fileId_{1}"/>成功上传</span>',record.id,record.data.fileId);break;
			case SWFUpload.FILE_STATUS.IN_PROGRESS :
				returnValue = String.format('<span id="{0}"><div id="fileId_{1}"/>正在上传</span>',record.id,record.data.fileId);break;
			default : 
				returnValue = String.format('<span id="{0}"><div id="fileId_{1}"/><font color="red">上传失败</font></span>',record.id,record.data.fileId);break;;
		}
		return returnValue;
		
	},
	
	//控制工具条上的按钮状态
	doControlBtns : function(isAddBtn){
		if(Ext.isEmpty(isAddBtn) || isAddBtn){
			var count = this.store.getCount();
			this.topBar.uploadFile.setDisabled(count < 1);
		}else{
			var b = this.topBar.uploadFile.state == 'pause';
			this.topBar.addFile.setDisabled(b);
			this.topBar.removeFile.setDisabled(b);
	        document.getElementById(this.swfupload.movieName).style.top = b?'30px':'-2px';
		}
	},
	
	//格式化时间
	formatTime : function(milliseconds) {
		var seconds = parseInt(milliseconds / 1000, 10);
		var h = 0,m = 0,s = 0,result = [];
		if (3599 < seconds) {
			h = parseInt(seconds / 3600, 10);
			seconds -= h * 3600;
		}
		if (59 < seconds) {
			m = parseInt(seconds / 60, 10);
			seconds -= m * 60;
		}
		result.push(String.leftPad(h, 2, '0'),':',String.leftPad(m, 2, '0'),':',String.leftPad(seconds, 2, '0'));
		return result.join('');
	}
});

使用方法:
var win = new Ext.ux.SwfUploadPanel({
    				btnOKHandler : function(){
    					alert('1111111111');
    				},
    				btnCancelHandler : function(){
    					alert('2222222222');
    				}
    			});
    			win.show();
可以参考组件中相关配置项,只要在实例组件时传入对应的参数就可以把组件中默认的给覆盖掉


单文件上传1:
/**
 * Swf文件上传组件
 * @class Ext.ux.SwfUploadField
 * @extends Ext.ux.ITrigger
 */
Ext.ux.SwfUploadField = Ext.extend(Ext.ux.ITrigger,{

	uploadUrl : 'uploadFiles.action',//文件上传到服务器上的URL
	postParams : {},//随文件上传提交的参数
	flashUrl : 'js/ext/resources/swfupload.swf',//flash文件地址
	filePostName : 'uploadFile.upload',
	fileSize : '5000 MB',//允许上传文件的最大的大小
	fileTypes : '*.*',//允许上传文件的类型
	fileTypesDescription : '所有文件',//允许上传文件类型说明
	enableClearBtn : true,//是否允许带有清除按钮,当选择了文件后
	
	//private
	trigger2Class : 'x-form-file-trigger',
	editable : false,
	flashHandlerId : Ext.id(),
	initComponent : function(){
		
		Ext.ux.SwfUploadField.superclass.initComponent.call(this);
		
	},
	
	//重写afterRender方法
	afterRender : function(){
		Ext.ux.SwfUploadField.superclass.afterRender.call(this);
		
		this.trigger.createChild({
            tag: 'div',
            id: this.flashHandlerId
        });
        
        this.initFlashConfig();//初始化flash设置
	},
	
	//重写onResize方法
	onResize : function(w,h){
		Ext.ux.SwfUploadField.superclass.onResize.call(this,w,h);
		this.width = w;
		if(this.swfupload){
			var leftOri = this.el.getComputedWidth();
			var leftPos = this.enableClearBtn && this.clearBtnVisiable?(leftOri + 18):leftOri;
			Ext.get(this.swfupload.movieName).setStyle({
	            position: 'absolute', 
	            top: '1px',
	            left: leftPos + 'px'
	        });
		}
		
	},
	
	onDisable : function(){
        this.getActionEl().addClass(this.disabledClass);
        this.el.dom.disabled = true;
        this.setHideTrigger(true);
        this.el.setWidth(this.width);
    },
    
    onEnable : function(){
        this.getActionEl().removeClass(this.disabledClass);
        this.el.dom.disabled = false;
        this.setHideTrigger(false);
        this.el.setWidth(this.width - 18);
    },
	
	initFlashConfig : function(){
		this.swfupload = new SWFUpload({
			upload_url : this.uploadUrl,
			post_params : Ext.isEmpty(this.postParams) ? {}:this.postParams,
			flash_url : this.flashUrl, 
			file_post_name : this.filePostName,
			file_size_limit : this.fileSize,
			file_types : this.fileTypes,
			file_types_description : this.fileTypesDescription,
			
			use_query_string:true,
			debug : false,
			button_width : '18',
			button_height : '20',
			button_placeholder_id : this.flashHandlerId,
			button_window_mode : SWFUpload.WINDOW_MODE.TRANSPARENT,
			button_cursor : SWFUpload.CURSOR.HAND,
			button_disabled : false,//按钮是否禁用,默认值为false
			button_action : SWFUpload.BUTTON_ACTION.SELECT_FILE, //设置Flash Button点击以后的动作,默认值为SWFUpload.BUTTON_ACTION.SELECT_FILES(多文件上传)
			//requeue_on_error, //是否将上传失败的的文件重新添加到上传队列的顶端,默认值为true。当文件上传失败或者停止上传触发uploadError事件,是否将上传失败的的文件重新添加到上传队列的顶端,当然调用cancelUpload方法触发uploadError事件,不会将文件重新添加到上传队列中,而是会丢弃
			custom_settings : {
				scope_handler : this
			},
			file_queued_handler : this.onAddFileToQueue,
			file_queue_error_handler : this.onAddFileToQueueError,
			file_dialog_complete_handler : this.onAddFileToQueueComplete,
			
			upload_start_handler : this.doUpload,
			upload_progress_handler : this.doUploadProgress,
			upload_error_handler : this.doUploadError,
			upload_success_handler : this.doUploadSuccess,
			upload_complete_handler : this.doUploadComplete
		});
		this.swfupload.uploadStopped = false;
		Ext.get(this.swfupload.movieName).setStyle({
            position: 'absolute', 
            top: '1px',
            left: (this.width - 20) + 'px'
        });
	},
	
	onAddFileToQueue : function(file){
		var thiz = this.customSettings.scope_handler;
		thiz.setValue(file.name);
	},
	
	//添加一个文件到队列中出现错误
	onAddFileToQueueError : function(file, errorCode, message){
		var thiz = this.customSettings.scope_handler;
		var errorMsg = '';
		switch(errorCode){
			case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE :
				errorMsg = String.format('<b>{0}</b>是0字节文件,不能上传0字节的文件',file.name);break;
			case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE :
				errorMsg = String.format('<b>{0}</b>是无效文件类型',file.name);break;
			default : 
				errorMsg = '选取文件时出现未知错误';
		}
		
		thiz.markInvalid(errorMsg);
	},
	
	//添加文件到数据表动作完成
	onAddFileToQueueComplete : function(selectedFilesCount, queuedFilesCount){
//		alert("selectedFilesCount:" + selectedFilesCount + "  queuedFilesCount:" + queuedFilesCount );
		var thiz = this.customSettings.scope_handler;
		thiz.doUpload();
	},
	
	doUpload : function(){
    	if (this.swfupload) {
    		this.swfupload.uploadStopped = false;
			var post_params = this.swfupload.settings.post_params;
			this.swfupload.setPostParams(post_params);
			this.swfupload.startUpload();
    	}
    },
    
    doUploadProgress : function(file, completeBytes, bytesTotal){
    	var thiz = this.customSettings.scope_handler;
    	var percent = Math.ceil((completeBytes / bytesTotal) * 100);
//    	Ext.getDom(thiz.progressElemId).innerHTML = percent + " %";
    },
    
    //当一个文件上传失败后调用此方法,cancelUpload方法调用后也会触发此事件
	doUploadError : function(file, errorCode, message){
		var thiz = this.customSettings.scope_handler;
		var tipMsg = null;
		try{
			switch(errorCode){
				case SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED :
					tipMsg = '上传失败,上传被终止';break;
				case SWFUpload.UPLOAD_ERROR.MISSING_UPLOAD_URL :
					tipMsg = '上传失败,丢失URL';break;
				case SWFUpload.UPLOAD_ERROR.IO_ERROR :
					tipMsg = '上传失败,IO异常';break;
				case SWFUpload.UPLOAD_ERROR.SECURITY_ERROR :
					tipMsg = '上传失败,安全错误';break;
				case SWFUpload.UPLOAD_ERROR.UPLOAD_LIMIT_EXCEEDED :
					tipMsg = '上传失败,大小限制异常';break;
				case SWFUpload.UPLOAD_ERROR.UPLOAD_FAILED :
					tipMsg = '上传失败,上传异常';break;
				case SWFUpload.UPLOAD_ERROR.SPECIFIED_FILE_ID_NOT_FOUND :
					tipMsg = '上传失败,文件编号丢失';break;
				case SWFUpload.UPLOAD_ERROR.FILE_VALIDATION_FAILED :
					tipMsg = '上传失败,验证失败';break;
				case SWFUpload.UPLOAD_ERROR.FILE_CANCELLED:
					tipMsg = '上传失败,文件取消';break;
			}
		}catch(e){
			
		}
		
		if(!Ext.isEmpty(tipMsg)){
			Ext.Msg.show({
				title : '提示',
			    msg : tipMsg,
			    width : 320,
			    buttons: Ext.Msg.OK,
			    fn: Ext.emptyFn,
			    icon: Ext.MessageBox.INFO
			});
		}
//		alert('onUploadError,errorCode:' + errorCode + ",message:" + message  + ",file.filestatus:" + file.filestatus);
	},
    
    /**当一个文件上传成功后调用些方法
	 * @param {} file 文件对象
	 * @param {} responseText 服务端响应的信息
	 * @param {} isResponsed 是否有服务端响应信息
	 */
	doUploadSuccess : function(file, responseText,isResponsed){
		var thiz = this.customSettings.scope_handler;
		try{
			if(Ext.util.JSON.decode(responseText).success){
				//处理上传完成后的动作
			}
		}catch(e){
			
		}
	},
    
    //文件上传动作完成
	doUploadComplete : function(file){
		var thiz = this.customSettings.scope_handler;
		if(thiz.enableClearBtn){
			thiz.triggers[0].show();
			thiz.clearBtnVisiable = true;
		}
		
	},
	
	onTrigger1Click : function(){
		this.setValue(null);
		if(this.enableClearBtn){
			this.triggers[0].hide();
			this.clearBtnVisiable = false;
		}
	}
	
});
Ext.reg('swffileuploadfield',Ext.ux.SwfUploadField);

//此组件的使用与使用Ext其它组件一样,可以指定xtype也可以下拉实例化


文件上传组件3:
/**
 * @class Ext.form.FileUploadField
 * @extends Ext.form.TwinTriggerField
 */
Ext.form.FileUploadField = Ext.extend(Ext.form.TwinTriggerField, {
	getTrigger : Ext.form.TwinTriggerField.prototype.getTrigger,
	initTrigger : Ext.form.TwinTriggerField.prototype.initTrigger,
	hideTrigger1 : true,
	trigger1Class : 'x-form-clear-trigger',
	trigger2Class : 'x-form-file-trigger',
	validationEvent : false,
	validateOnBlur : false,
	editable : false,
	enableClearBtn : true,//是否启用清除选择文件按钮

	initComponent : function() {
		Ext.form.FileUploadField.superclass.initComponent.call(this);

		// add the CSS here so we don't have to include it
		if (Ext.util.CSS.getRule('.x-form-file') == null) {
			var styleBody = '.x-form-file-cabinet {position: relative;}'
					+ '.x-form-file-wrapper {position: absolute; display: block; height: 22px; width: 18px; overflow: hidden;}'
					+ '.x-form-file {cursor: pointer; position: absolute; height: 22px; right: 0; opacity: 0; -moz-opacity: 0; filter: alpha(opacity=0);}';

			var styleSheet = Ext.util.CSS.createStyleSheet('/* Ext.form.FileUploadField stylesheet */\n' + styleBody, 'FileUploadField');
			Ext.util.CSS.refreshCache();
		}

		this.addEvents(
				/**
				 * @event fileselected Fires when the underlying file input
				 *        field's value has changed from the user selecting a
				 *        new file from the system file selection dialog.
				 * @param {Ext.form.FileUploadField} this
				 * @param {String} value The file value returned by the underlying file input field
				 */
				'fileselected');

		this.triggerConfig = {
			tag : 'span',
			cls : 'x-form-twin-triggers',
			cn : [{
						tag : 'img',
						src : Ext.BLANK_IMAGE_URL,
						cls : 'x-form-trigger ' + this.trigger1Class
					}, {
						tag : 'img',
						src : Ext.BLANK_IMAGE_URL,
						cls : 'x-form-trigger ' + this.trigger2Class
					}, {
						tag : 'span',
						cls : 'x-form-file-cabinet',
						cn : [{
									tag : 'div',
									id : this.getFileWrapperId(),
									cls : 'x-form-file-wrapper'
								}]
					}]
		};
	},

	onRender : function(ct, position) {
		Ext.form.FileUploadField.superclass.onRender.call(this, ct,position);
		this.wrapper = Ext.get(this.getFileWrapperId());

		this.createFileInput();
		this.bindListeners();

		this.getTrigger(1).on({
					mousemove : {
						fn : function() {
							this.wrapper.setXY(this.getTrigger(1).getXY())
						},
						scope : this
					}
				});
	},

	bindListeners : function() {
		this.fileInput.on({
			scope : this,
			mouseenter : function() {
				this.getTrigger(1).addClass('x-form-trigger-over')
			},
			mouseleave : function() {
				this.getTrigger(1).removeClass('x-form-trigger-over')
			},
			mousedown : function() {
				this.getTrigger(1).addClass('x-form-trigger-click')
			},
			mouseup : function() {
				this.getTrigger(1).removeClass('x-form-trigger-click')
			},
			change : {
				fn : this.handleFile,
				scope : this
			}
		});
	},

	reset : function() {
		Ext.form.FileUploadField.superclass.reset.call(this);
		this.fileInput.remove();
		this.createFileInput();
		this.bindListeners();
		if(this.enableClearBtn){
			this.getTrigger(0).hide();
		}
	},

	setValue : Ext.form.TwinTriggerField.prototype.setValue.createSequence(function(v) {
		this.getEl().dom.qtip = v;
		this.getEl().dom.qwidth = Ext.util.TextMetrics.measure(this.getEl(), v).width + 12;

		if (Ext.QuickTips) {
			Ext.QuickTips.enable();
		}
	}),

	handleFile : function() {
		// if this is unix style structure replace / with \
		var filePath = this.fileInput.dom.value.replace(/\//g, '\\');

		// extract the filename from the value
		var indexPos = filePath.lastIndexOf('\\');
		var fileName = filePath.substring(indexPos + 1);

		this.setValue(fileName);
		this.fireEvent('fileselected', this, fileName);
		if(this.enableClearBtn){
			this.getTrigger(0).show();
		}
	},

	onDestroy : function() {
		Ext.form.FileUploadField.superclass.onDestroy.call(this);
		Ext.destroy(this.fileInput, this.wrapper);
	},

	onDisable : function() {
		Ext.form.FileUploadField.superclass.onDisable.call(this);
		this.doDisable(true);
	},

	onEnable : function() {
		Ext.form.FileUploadField.superclass.onEnable.call(this);
		this.doDisable(false);
	},

	doDisable : function(disabled) {
		this.fileInput.dom.disabled = disabled;
	},

	preFocus : Ext.emptyFn,

	onTrigger1Click : function() {
		this.clearValue();
		if(this.enableClearBtn){
			this.getTrigger(0).hide();
		}
		this.fileInput.remove();
		this.createFileInput();
		this.bindListeners();
	},

	createFileInput : function() {
		this.fileInput = this.wrapper.createChild({
			id : this.getFileInputId(),
			name : this.name || this.getId(),
			cls : 'x-form-file',
			tag : 'input',
			type : 'file',
			width : 1
		});
	},

	clearValue : function() {
		this.setRawValue('');
		this.setValue('');
		this.value = '';
	},

	getFileInputId : function() {
		return this.id + '-file';
	},

	getFileWrapperId : function() {
		return this.id + '-wrapper';
	}
});
Ext.reg('fileuploadfield', Ext.form.FileUploadField);
//使用方法同上


附件中有组件使用效果图
  • 大小: 24.2 KB
  • 大小: 48.4 KB
  • 大小: 57.2 KB
  • 大小: 9.7 KB
  • 大小: 51.2 KB
分享到:
评论
11 楼 TimeTTTTT 2016-06-07  
     
10 楼 TimeTTTTT 2016-06-07  
     
9 楼 TimeTTTTT 2016-06-07  
     
8 楼 TimeTTTTT 2016-06-07  
     
7 楼 TimeTTTTT 2016-06-07  
    
6 楼 TimeTTTTT 2016-06-07  
   
5 楼 TimeTTTTT 2016-06-07  
 
4 楼 TimeTTTTT 2016-06-07  
        
3 楼 TimeTTTTT 2016-06-07  
    
2 楼 TimeTTTTT 2016-06-07  
    
1 楼 TimeTTTTT 2016-06-07  
[color=gray][/color]11151515151515151515151515151515[i][b][img][url][flash=200,200][align=center][siz[flash=200,200][url][img][list]
[*]
引用

[/list][/img][/url][/flash]e=small][/size][/align][/flash][/url][/img] [/b][/i]

相关推荐

    EXTJS 多文件上传

    总的来说,EXTJS的`MultiFileUploadField` 是一个强大且灵活的多文件上传解决方案,它结合了现代Web技术,提供了优秀的用户体验和丰富的开发者接口。通过合理利用这个组件,开发者可以快速构建出功能完善的文件上传...

    extjs 4.2 多文件上传

    用Ext编写的多文件上传组件,已封装。 支持多文件上传,文件下载,文件删除,

    ExtJS原生多文件拖动上传组件

    ExtJS原生多文件拖动上传组件 使用时修改包路径 1.多文件上传 2.支持拖动上传 3.支持图片压缩 4.支持图片合并 5.文件排序 可扩展实时图片预览 api //初始化画板 initCanvas //上传文件窗口 uploadWindow //初始化...

    extjs多文件上传

    默认情况下,这个组件只支持单文件上传,但通过扩展和定制,可以实现多文件上传的功能。 1. **实现多文件上传**:要实现多文件上传,首先需要扩展`Ext.form.field.File`组件,增加一个文件选择框,允许用户选择多个...

    ExtJS 多文件上传 UploadDialog For ExtJS3.x

    本篇文章将详细介绍如何针对ExtJS 3.x版本定制和优化一个名为`UploadDialog`的多文件上传组件。 #### 关键技术点 1. **ExtJS 3.x兼容性** - 在ExtJS 2.x版本中实现的多文件上传功能通常无法直接应用于3.x版本。 ...

    EXTJS3.0多文件上传组件

    综上所述,EXTJS3.0多文件上传组件结合了EXTJS的组件化开发优势和SWFUpload的多文件上传功能,为开发者提供了一个高效且易于定制的文件上传解决方案。通过深入理解和掌握相关知识点,可以开发出满足不同需求的多文件...

    extjs 多文件上传

    在ExtJS中实现多文件上传功能,能够极大地提升用户体验,特别是在处理大量数据或文件时。本篇文章将详细探讨如何使用ExtJS实现多文件上传,并涵盖相关的关键知识点。 一、ExtJS 文件上传组件 在ExtJS中,我们可以...

    批量上传文件 EXTJS文件上传 上传组件

    EXTJS的文件上传组件提供了方便的方式来处理这些任务,允许用户一次性选择多个文件进行上传,极大地提高了工作效率。 批量上传文件的核心在于利用HTML5的File API,这个API允许前端程序对用户的本地文件进行操作,...

    ExtJS4多文件上传,带进度条及管理

    总之,"ExtJS4多文件上传,带进度条及管理"是Web开发中的高级功能,它结合了ExtJS4的组件化开发优势和swfupload的高效上传能力,为用户提供了一流的文件上传体验。开发者需要掌握相关技术和API,才能灵活地实现这一...

    Extjs多文件上传

    在“Extjs多文件上传”这个主题中,我们将深入探讨如何使用ExtJS实现一个支持自由添加和减少上传文件个数的多文件上传功能。 首先,ExtJS的文件上传功能通常依赖于其组件系统,特别是`Ext.form.FileField`(也称为`...

    ExtJS验证上传文件类型

    ExtJS 中实现文件上传功能是非常方便的,但对于新手来说,控制文件上传类型是一个难题。例如,我们只想让用户上传特定的文件类型,例如txt文件,那么如何实现当用户上传非txt文件时,给出错误提示呢?这篇文章将详细...

    extjs 多文件上传控件

    在ExtJS中,多文件上传控件是开发人员常用的一种功能,用于在网页上实现批量上传多个文件。这种控件允许用户一次性选择并上传多个文件,极大地提升了用户体验。 在ExtJS中实现多文件上传,主要涉及到以下几个关键...

    extjs 多文件上传代码实例

    而"FileUploadPanel"可能是一个自定义的ExtJS组件类,扩展了基础的FormPanel,专门用于多文件上传。如果存在这个类,你可以通过继承和扩展FormPanel,添加更多的定制功能,如进度条显示、错误处理等。 总的来说,...

    Structs2+ExtJs多文件上传,多选文件加入列表

    本教程将专注于使用Structs2和ExtJS实现多文件上传的功能,包括多选文件、进度条显示以及传输速度监控等特性。 Structs2是一个基于Java的MVC框架,它提供了灵活的控制器、模型和视图结构,简化了Web应用的开发过程...

    ExtJS实现多文件上传UploadDialog For ExtJS3.x

    综上所述,实现ExtJS 3.x的多文件上传功能,需要结合Struts2框架,完成前后端的配置、实体模型的定义、Action的编写,以及ExtJS组件的使用。这一过程涉及到了HTTP文件上传、JSON数据交换、数据库操作等多个技术点,...

    Extjs4文件上传,后台struts2

    综上所述,通过结合ExtJS 4的文件上传组件和Struts2的Action,我们可以实现一个完整的文件上传功能。用户可以在前端选择文件,然后通过Struts2的Action进行后端处理,包括验证、存储等操作。在实际项目中,你可能还...

    extjs5.1多文件上传控件

    标题中的“ExtJS5.1多文件上传控件”指的是在Web应用中使用ExtJS框架的一个功能组件,它允许用户一次选择并上传多个文件。ExtJS是一个强大的JavaScript库,专门用于构建富客户端的桌面级Web应用程序。在版本5.1中,...

    extjs4 文件上传

    在EXTJS 4.0版本中,文件上传功能是一个重要的组成部分,它允许用户方便地将多个文件上传到服务器。EXTJS是一个强大的JavaScript框架,专为构建富客户端Web应用程序设计,其组件化和可定制性是其核心优势。下面将...

    ExtJS带进度条的多文件上传和图片预览

    在"ExtJS带进度条的多文件上传和图片预览"这个项目中,它展示了如何利用ExtJS来实现一个高效且用户友好的文件上传功能,尤其适用于处理大量或大体积的文件。下面将详细介绍这个项目中的关键知识点。 1. **ExtJS组件...

Global site tag (gtag.js) - Google Analytics