function SwfUploader(opt)
{
	/**
	 * opt对象说明：
	 * @param id 	这是将要生成的flash DOM对象的ID值
	 * @param path	这是flash回调js时的对象获取代码，比如获取对象代码为g_loader_list.getById('123456')，则path应该取值为字符串"g_loader_list.getById('123456')"
	 * @param container	这是DOM对象的容器DOM，可以为JQuery对象。生成的flash DOM将被apped在此容器内。
	 * @param maxFileSize 可以上传的最大文件尺寸
	 * @param talkBox	数据参数。微博专用。
	 * @param src	flash文件的url，默认为/swf/file_uploader.swf
	 * @param w	flash对象的宽
	 * @param h	flash对象的高
	 * @param bgcolor flash的默认背景色，缺省值为0xF2F2F2
	 * @param vars	flash对象的flashvar参数，用来初始化flash上传逻辑。这是一个键值对列表，形式类似key1=values1&key2=value2，可用的key有：
	 * 					bg		flash背景图片文件的url，不指定则无背景
	 * 					bg_sel	flash已选择文件后的背景图片文件的url，不指定则使用bg参数指定的背景
	 * 					bg_up	flash正在上传文件的背景图片文件的url，不指定则使用bg参数指定的背景
	 * 					bg_fin	flash上传完毕背景图片文件的url，不指定则使用bg参数指定的背景
	 *					bg_hover		鼠标悬停时，flash背景图片文件的url，不指定则使用bg参数指定的背景
	 * 					bg_sel_hover	鼠标悬停时，flash已选择文件后的背景图片文件的url，不指定则使用bg_sel参数指定的背景
	 * 					bg_up_hover		鼠标悬停时，flash正在上传文件的背景图片文件的url，不指定则使用bg_up参数指定的背景
	 * 					bg_fin_hover	鼠标悬停时，flash上传完毕背景图片文件的url，不指定则使用bg_fin参数指定的背景
	 *
	 *
	 * flash提供了一些接口，大部分不需要自己调用（或者使用SwfUploader类提供的方法间接调用），一下列举可能需要自己调用的接口：
	 * @addFileFilter(description:String, formatList:String)
	 *			添加一个文件后缀过滤器，@description为描述，@formatList为后缀列表，形式为'*.pdf;*.txt;*.jpg'
	 *			例如：addFileFilter('图片文件','*.bmp;*.jpg;*.gif');
	 * @delFileFilter(description:String, formatList:String)
	 *			删除文件后缀过滤器，方法同@addFileFilter
	 * @setText(t:String)
	 *			设置flash上显示的文本。默认没有文本。这段文本将居中显示。
	 * @setTextColor(c:uint)
	 *			设置flash上文本的颜色。默认颜色为0x333333。
	 *
	 *
	 * fileList里面包含了所有选择了的文件，对于其中的一个file，它具有如下属性
	 *		file.sizeT = this.sizeText(file.size);	//文件尺寸的文本形式，如12K，30M，945B
	 *		file.sid = sid;		//文件是在第几次选择进入文件列表的
	 *		file.sindex = i;	//文件是在该次选择的文件中的第几个
	 *							//Note: 很多事件响应函数都提供了sid和sindex这两个参数，sid表示第几次选择文件，sindex表示本次选择的文件中的第几个文件。通过uploader.findFile(sid,sindex)可以找到该文件在fileList中的下标
	 *		file.type = file.type.toLowerCase();	//文件的后缀，小写
	 *		file.uploadMode = 0;//0为普通上传，1为上传压缩数据		//是否启用压缩上传，暂不支持
	 *		file.vars = {of:'json',cookie:document.cookie};			//上传文件时的额外参数
	 *		//对于某个等待上传的文件file，为file指定vars属性可在上传文件时提供额外的参数。如:file.vars={filename:"123.jpg"}，后台接收文件时可获取到POST参数filename，值为123.jpg
	 *
	 *
	 * 使用方法：
	 * 		var uploader = new SwfUploader({...});	//生成文件上传器
	 * 		uploader.initSwf = fucntion() {...};	//重载swf初始化方法，可以在这个方法里添加过滤器等
	 *		uploader.uploadFieldName = function() {...};	//重载此方法，可以为每个文件指定POST的field
	 * 		uploader.eventSwfSelect = function() {...};	//设置文件选择事件响应函数。还有多个事件可响应，可自行阅读代码，查找eventSwf开头的函数
	 *		uploader.installSwf();	//生成flash DOM对象，将对象放置在指定的容器DOM内
	 *		//此时等待用户选择，然后可使用uploader.startAutoUpload()启动上传。
	 */
	opt=$.extend({id:'swf_file_uploader',path:'swf',container:null,maxFileSize:80*1024*1024,talkBox:null,src:null, w:null, h:null, bgcolor:'#F2F2F2', vars:{}},opt);
	this.id = opt.id;
	this.path = opt.path;
	this.swfCon=opt.container;
	this.maxFileSize = opt.maxFileSize;
	this.fileList = [];//文件状态 -4:用户取消上传 -3:上传出错 -2:文件格式错误 -1:文件过大 0:等待上传 1:正在上传 2:上传完毕，并正确处理 3:上传完毕，但处理出错 4:上传过程出错 5:返回包无法解析 6:正在压缩 7:压缩失败
	this.browserIndex = [];
	this.current_div = null;//储存当前要上传图片的编辑框div
    
	this.t = opt.talkBox;//传递窗口对象来处理数据
	this.imageBoxAll = [];
	this.attachBoxAll = [];
	//某次上传任务的相关数据
	this.autoUploading = false;//正在执行自动上传
	this.curUpload = -1;//当前正在上传的文件，用于取消上传时迅速中断上传
	this.fileCountNeedUpload = 0;
	this.fileCountUploaded = 0;
	this.fileCountCanceled = 0;
	this.fileCountFormatError = 0;
	this.fileCountSizeError = 0;
	this.fileCountFatalError = 0;
	this.bytesNeedUpload = 0;
	this.bytesUploaded = 0;
	this.startTime = 0;
	this.w = (opt.w==null?75:opt.w);
	this.h = (opt.h==null?26:opt.h);
	this.src =(opt.src==null?'/swf/file_uploader.swf':opt.src);
	if(typeof(opt.wmode)=='undefined'||opt.wmode==null||opt.wmode.length==0)
		this.wmode = opt.wmode = 'transparent';
	else
		this.wmode = opt.wmode;
	if(opt.wmode=='transparent')
		opt.bgcolor = '';
	
	this.uploadUrl = function(offset)
	{
		return '/photo/upload';
	};
	this.uploadFieldName = function(offset) { return 'file'; }
	
	this.installSwf = function()
	{
		var varstr = '';
		opt.vars.handler = this.path;
		for(var n in opt.vars)
		{
			if(varstr.length>0)
				varstr += '&';
			varstr += n+'='+encodeURIComponent(opt.vars[n]);
		}
		var obj={w:this.w,h:this.h,id:this.id,src:this.src,wmode:opt.wmode,vars:varstr,container:this.swfCon,bgcolor:opt.bgcolor};
		obj.src+='?'+Math.random();
		return $.swf(obj);
	};
	
	this.swf = function()
	{
		return $.swf(this.id);
	}
	
	this.initSwf = function()
	{
		//this.swf().addFileFilter('图片文件 (可一次选择多张图片)','*.jpg;*.jpeg;*.gif;*.bmp;*.png;');
		//try{this.swf().config(this.maxFileSize-500,900,900);}catch(e){};
	};
	
	this.findFile = function(sid, sindex)
	{
		if(this.browserIndex['sid_'+sid]!=undefined)
		{
			var iFile = this.browserIndex['sid_'+sid]+sindex;
			if(iFile<=this.fileList.length-1)
				return iFile;
		}
		return -1;
	};
	
	this.swfSelect = function(sid,file_list)
	{
		//$.dbgln('swfSelect');
		this.browserIndex['sid_'+sid] = this.fileList.length;
		for(var i=0;i<file_list.length; ++i)
		{
			var file = file_list[i];
			//file.sizeInK = this.sizeInK(file.size);
			file.sizeT = this.sizeText(file.size);
			file.sid = sid;
			file.sindex = i;
			file.type = file.type.toLowerCase();
			file.uploadMode = 0;//0为普通上传，1为上传压缩数据
			file.vars = {of:'json',nauth:$.cookie('nauth')};
		
			if(file.size<2)
			{
				++this.fileCountFormatError;
				file.status = -2;
			}
			/*else if(file.size>this.maxFileSize && this.fileCanCompress(file))
			{
				file.status = 0;
				file.uploadMode = 1;
			}*/
			else if(file.size>this.maxFileSize)
			{
				++this.fileCountSizeError;
				file.status = -1;
			}
			else
			{
				file.status = 0;
			}

			this.fileCountNeedUpload ++;
			this.fileList.push( file );
		}
		if(this.fileCountNeedUpload>0)
			this.swf().setStatus(1);
		this.countBytesNeedUpload();
		if(this.eventSwfSelect)
			 this.eventSwfSelect(sid, file_list.length);
	};
	
	this.swfCancel = function(sid)
	{
		if(this.eventSwfCancel)
			this.eventSwfCancel();
	};
	
	this.swfComplete = function(sid, sindex)
	{
		//$.dbgln('swfComplete');
		var iFile = this.findFile(sid,sindex);
		if(-1!=iFile && this.eventSwfComplete)
			this.eventSwfComplete(iFile);
	};
	
	this.swfHttpStatus = function(status, sid, sindex)
	{
		//$.dbgln('swfHttpStatus');
		var iFile = this.findFile(sid,sindex);
		if(-1!=iFile && this.eventSwfHttpStatus)
			this.eventSwfHttpStatus(status, iFile);
	};
	
	this.swfIoError = function(text, sid, sindex)
	{
		//$.dbgln('swfIoError');
		var iFile = this.findFile(sid,sindex);
		if(-1!=iFile)
		{
			this.fileList[iFile].status = 4;
			++this.fileCountFatalError;
			this.autoUploading = false;
			if(this.eventSwfIoError)
				this.eventSwfIoError(text, iFile);
		}
	};
	
	this.swfOpen = function(sid, sindex)
	{
		this.swf().setStatus(2);
		//$.dbgln('swfOpen');
		var iFile = this.findFile(sid,sindex);
		if(-1!=iFile && this.eventSwfOpen)
			this.eventSwfOpen(iFile);
	};
	
	this.swfProgress = function(bytesLoaded, bytesTotal, sid, sindex)
	{
		this.swf().setStatus(2);
		//dbgln('swfProgress '+bytesLoaded+' '+bytesTotal);
		var iFile = this.findFile(sid,sindex);
		if(-1!=iFile && this.eventSwfProgress)
		{
			this.eventSwfProgress(bytesLoaded, bytesTotal, iFile);
		}
	};
	
	this.swfSecurityError = function(text, sid, sindex)
	{
		//$.dbgln('swfSecurityError');
		var iFile = this.findFile(sid,sindex);
		if(-1!=iFile)
		{
			this.fileList[iFile].status = 4;
			++this.fileCountFatalError;
			this.autoUploading = false;
			if(this.eventSwfSecurityError)
				this.eventSwfSecurityError(text, iFile);
		}
	};
	
	this.swfUploadCompleteData = function(data, sid, sindex)
	{
		//$.dbgln('swfUploadCompleteData:'+data);
		var iFile = this.findFile(sid,sindex);
		if(-1!=iFile)
		{
			try
			{
				data = data.replace(/\r/g, '\\r').replace(/\n/g,'\\n');
				eval('var ret='+data);
			}
			catch(e)
			{
				$.dbgln('return json exception:'+e.description);
				this.fileList[iFile].status = 5;
				++this.fileCountFatalError;
				this.autoUploading = false;
				if(this.eventSwfUploadCompleteDataException)
					this.eventSwfUploadCompleteDataException(data,iFile);
				return;
			}
			//var ret = jQuery.parseJSON(data);
			if(ret.result==0)
			{
				this.fileList[iFile].status = 2;
				this.fileCountUploaded ++;
				this.bytesUploaded += this.fileList[iFile].size;
			}
			/*else if(ret.result==301)
			{
				this.fileList[iFile].status = -1;
				++this.fileCountSizeError;
			}
			else if(ret.result==300)
			{
				this.fileList[iFile].status = -2;
				++this.fileCountFormatError;
			}*/
			else
			{
				//$.dbgln('swfUploadCompleteData:'+data);
				this.fileList[iFile].status = 3;
				++this.fileCountFatalError;
			}
			if(this.autoUploading)
			{
				if(this.eventSwfUploadCompleteData)
				{
					if(this.eventSwfUploadCompleteData(ret, iFile))
					{
						if(this.findWaitingFile(iFile+1)>0)
							this.upload(iFile+1);
						else
							this.stopAutoUpload();
					}
					/*
					else if(ret.result==0)
					{
						this.upload(iFile+1);
					}
					*/
					else
					{
						this.autoUploading = 0;
						this.swf().setStatus(3);
						this.stopAutoUpload();
					}
					
				}
			}
			else
			{
				this.autoUploading = 0;
				this.swf().setStatus(3);
			}
		}
	};
	
	this.swfLoadIoError = function(sid,sindex)
	{
		//$.dbgln('swfLoadIoError');
		var iFile = this.findFile(sid,sindex);
		if(-1!=iFile)
		{
			var file = this.fileList[iFile];
			if(file.size>this.maxFileSize)
			{
				++this.fileCountSizeError;
				file.status = -1;
				if(this.eventSwfCompressFail)
					this.eventSwfCompressFail(iFile);
				this.upload(this.curUpload+1);//上传下一个文件
			}
			else
			{
				file.status = 0;
				file.uploadMode = 0;
				if(this.eventSwfCompressFail)
					this.eventSwfCompressFail(iFile);
				this.upload(this.curUpload);//按照普通方式重新上传此文件
			}
		}
	};
	
	this.swfLoadComplete = function(sid,sindex)
	{
		//$.dbgln('swfLoadComplete');
		var iFile = this.findFile(sid,sindex);
		if(this.eventSwfLoadComplete)
			this.eventSwfLoadComplete(iFile);
	};
	
	this.swfCompressFail = function(sid,sindex)
	{
		//$.dbgln('swfCompressFail');
		var iFile = this.findFile(sid,sindex);
		if(-1!=iFile)
		{
			var file = this.fileList[iFile];
			if(file.size>this.maxFileSize)
			{
				++this.fileCountSizeError;
				file.status = -1;
				if(this.eventSwfCompressFail)
					this.eventSwfCompressFail(iFile);
				//$.dbgln('上传下一个');
				this.upload(this.curUpload+1);//上传下一个文件
			}
			else
			{
				file.status = 0;
				file.uploadMode = 0;
				if(this.eventSwfCompressFail)
					this.eventSwfCompressFail(iFile);
				//$.dbgln('按普通方式重新上传,curUpload='+this.curUpload);
				this.upload(this.curUpload);//按照普通方式重新上传此文件
			}
		}
	};
	
	this.swfNotNeedCompress = function(sid,sindex)
	{
		//$.dbgln('swfNotNeedCompress');
		var iFile = this.findFile(sid,sindex);
		if(-1!=iFile)
		{
			var file = this.fileList[iFile];
			file.uploadMode = 0;
			file.status = 0;
			if(this.eventSwfNotNeedCompress)
				this.eventSwfNotNeedCompress(iFile);
			this.upload(this.curUpload);
		}
	};
	
	this.swfCompressOk = function(newsize,sid,sindex)
	{
		//$.dbgln('swfCompressOk');
		var iFile = this.findFile(sid,sindex);
		if(iFile>=0)
		{
			var file = this.fileList[iFile];
			file.size = newsize;
			file.status = 1;
			this.countBytesNeedUpload();
			if(this.eventSwfCompressOk)
				this.eventSwfCompressOk(iFile);
			this.swf().upload(file.sid, file.sindex, this.uploadUrl(iFile), this.uploadFieldName(iFile));
		}
	}
	
	this.findWaitingFile = function(offset)
	{
		offset |= 0;
		for(var i=offset;i<this.fileList.length;++i)
		{
			var status = this.fileList[i].status;
			if(0==status || 4==status)
				return i;
		}
		return -1;
	};
	
	this.startAutoUpload = function(offset)
	{
		//$.dbgln('startAutoUpload, offset='+offset);
		offset |= 0;
		if(!this.autoUploading)
		{
			this.autoUploading = true;
			this.curUpload = offset;
			this.startTime = Date.parse(new Date());

			if(this.eventStartAutoUpload)
				this.eventStartAutoUpload(offset);
			this.upload(offset);
		}
	};
	
	this.stopAutoUpload = function()
	{
		if(this.autoUploading)
		{
			this.autoUploading = false;
			var file = this.fileList[this.curUpload];
			this.swf().cancel(file.sid, file.sindex);
			if(this.eventStopAutoUpload)
				this.eventStopAutoUpload();
			
			if(this.eventAutoUploadOver)
				this.eventAutoUploadOver(true);
		}
	};
	
	this.browse = function(obj)
	{
	    this.current_div = $(obj);alert('trigger');
	    //this.swf().fileBrowse();
		$('#swf_file_uploader').trigger('click');
		//document[this.id].fileBrowse();
	}
	
	this.upload = function(offset)
	{
		//$.dbgln('upload, offset='+offset);
		var iFile = this.findWaitingFile(offset);
		if(iFile>=0)
		{
			this.curUpload = iFile;
			var file = this.fileList[iFile];
			//$.dbgln('in upload(),file.uploadMode='+file.uploadMode);
			if(1==file.uploadMode)
			{
				//$.dbgln('in upload() 压缩上传');
				file.status = 6;
				if(this.eventStartCompress)
				{
					this.eventStartCompress(iFile);
				}
				this.swf().compress(file.sid,file.sindex);
			}
			else
			{
				//$.dbgln('in upload() 普通上传');
				file.status = 1;
				//$.dbgln(this.uploadUrl(iFile));
				this.swf().upload(file.sid, file.sindex, this.uploadUrl(iFile), this.uploadFieldName(iFile), file.vars);
			}
		}
		else
		{
			this.autoUploading = false;
			if(this.fileCountUploaded>0)
				this.swf().setStatus(3);
			else
				this.swf().setStatus(0);
			if(this.eventAutoUploadOver)
				this.eventAutoUploadOver(true);
		}
	};
	
	this.cancel = function(offset)
	{
		//$.dbgln('user cancel, offset='+offset);
		var file = this.fileList[offset];
		if(file.status==0)
		{
			file.status=-4;
			++this.fileCountCanceled
			return true;
		}
		else if(file.status==1)
		{
			file.status=-4;
			++ this.fileCountCanceled;
			this.swf().cancel(file.sid, file.sindex);
		}
		return false;
	};
	
	this.reset = function()
	{
		if(!this.autoUploading)
		{
			this.fileCountNeedUpload = 0;
			this.fileCountUploaded = 0;
			this.bytesNeedUpload = 0;
			this.bytesUploaded = 0;
			this.fileCountFormatError = 0;
			this.fileCountSizeError = 0;
			this.fileCountFatalError = 0;
			while(this.fileList.length)
				this.fileList.pop();
			if(this.swf())
				this.swf().reset();
			return true;
		}
		return false;
	};
	
	this.fileTypeCss = function(type)
	{
		type=type.toLowerCase();
		switch(type)
		{
			case ".bmp":return "bmpIcon";
			case ".gif":return "gifIcon";
			case ".png":return "pngIcon";
			case ".jpg":
			case ".jpeg":return "jpgIcon";
			case ".doc":
			case ".docx":return "docIcon";
			case ".xls":
			case ".xlsx":return "xlsIcon";
			case ".ppt":
			case ".pptx":return "pptIcon";
			case ".txt":return "txtIcon";
			case ".pdf":return "pdfIcon";
			case ".rtf":return "rtfIcon";
		}
		return "";
	};
	
	this.sizeInK = function(s)
	{
		return $.sprintf("%.3f",s/1024);
	};
	
	this.fileCanCompress = function(file)
	{
		if($.swfVersion()[0]>=10)
		{
			if(file.type=='.jpg' || file.type=='.jpeg' || file.type=='.png')
			{
				return true;
			}
		}
		return false;
	};
	
	this.countBytesNeedUpload = function()
	{
		var c=0;
		for(var i=0;i<this.fileList.length;++i)
		{
			c+=this.fileList[i].size;
		}
		this.bytesNeedUpload = c;
	};
	
	this.sizeText=function(s)
	{
		s = parseFloat(s);
		if(s>1024*1024)
			return $.sprintf("%3.2f", s/1024/1024)+'M';
		else if(s>1024)
			return $.sprintf("%4.2f", s/1024)+'K';
		else
			return $.sprintf("%d", s)+'B';
	};
	
};
