一个Ext2+SWFUpload做的图片上传对话框

一个Ext2+SWFUpload做的图片上传对话框的例程

我们先看看对话框的布局:

布局就是在一个窗口里内嵌一个表格控件,窗口的底部工具条带一个进度条,表格的顶部工具条带几个操作按钮和一个下来选择框,底部工具条作为一个信息显示区域显示文件的总数和总的上传大小。
我们来分析一下uploadDialog.js文件:
  
  
  
  
  1. var Application={};  
  2.  
  3.        Application.uploadDialog={  
  4.  
  5.                 
  6.  
  7.               progressBarText:'正在上传:{0},{1}%完成',  
  8.  
  9.                 
  10.  
  11.               statuBarText:'文件总数:{0}个  ,大小:{1}',  
  12.  
  13.                 
  14.  
  15.               show:function(data){  
  16.  
  17.                      if(!this.dialog)  
  18.  
  19.                             this.initDialog();  
  20.  
  21.                      //this.uploadGrid.store.removeAll();  
  22.  
  23.                      if(data)  
  24.  
  25.                            this.classStore.loadData(data);  
  26.  
  27.                      this.uploadAction[0].enable();  
  28.  
  29.                      this.uploadAction[1].disable();  
  30.  
  31.                      this.uploadAction[2].disable();  
  32.  
  33.                      this.uploadAction[3].disable();  
  34.  
  35.                      this.uploadAction[4].enable();  
  36.  
  37.                      //this.uploadProgressBar.updateProgress(0,'');  
  38.  
  39.                      this.dialog.show();  
  40.  
  41.               },  
  42.  
  43.    
  44.  
  45.               hide:function(){  
  46.  
  47.                      this.dialog.hide();  
  48.  
  49.               },  
  50.  
  51.    
  52.  
  53.               classStore:new Ext.data.SimpleStore({fields: ["id""text"],data:[]}),  
  54.  
  55.                 
  56.  
  57.               uploadAction:[  
  58.  
  59.                      new Ext.Action({text:'增加',  
  60.  
  61.                             handler:function(){  
  62.  
  63.                                    Application.uploadDialog.swfu.selectFiles();  
  64.  
  65.                             }  
  66.  
  67.                      }),  
  68.  
  69.                      new Ext.Action({text:'删除',disabled:true,handler:function(){  
  70.  
  71.                             var obj=Application.uploadDialog;  
  72.  
  73.                             var grid=obj.uploadGrid;  
  74.  
  75.                             var store=grid.store;  
  76.  
  77.                             var selection=grid.getSelectionModel().getSelections();  
  78.  
  79.                             for(var i=0;i<selection.length;i++){  
  80.  
  81.                                    var rec=store.getAt(store.indexOfId(selection[i].id));  
  82.  
  83.                                    obj.swfu.cancelUpload(rec.data.id);  
  84.  
  85.                                    store.remove(rec);  
  86.  
  87.                             }  
  88.  
  89.                             obj.stateInfo.getEl().innerHTML=String.format(obj.statuBarText,obj.uploadGrid.store.getCount(),Ext.util.Format.fileSize(obj.uploadGrid.store.sum('size')));  
  90.  
  91.                             if(obj.uploadGrid.store.getCount()==0){  
  92.  
  93.                                    obj.uploadGrid.store.removeAll();  
  94.  
  95.                                    obj.uploadAction[1].disable();  
  96.  
  97.                                    obj.uploadAction[2].disable();  
  98.  
  99.                                    obj.uploadAction[3].disable();  
  100.  
  101.                             }  
  102.  
  103.                      }}),  
  104.  
  105.                      new Ext.Action({text:'清空',disabled:true,handler:function(){  
  106.  
  107.                             var obj=Application.uploadDialog;  
  108.  
  109.                             var store=obj.uploadGrid.store;  
  110.  
  111.                             var len=store.getCount();  
  112.  
  113.                             for(var i=0;i<len;i++){  
  114.  
  115.                                    var rec=store.getAt(i);  
  116.  
  117.                                    obj.swfu.cancelUpload(rec.data.id);  
  118.  
  119.                             }  
  120.  
  121.                             store.removeAll();  
  122.  
  123.                             obj.classCombo.clearValue();  
  124.  
  125.                             obj.stateInfo.getEl().innerHTML=String.format(obj.statuBarText,0,Ext.util.Format.fileSize(0));  
  126.  
  127.                             obj.uploadProgressBar.updateProgress(0,'');  
  128.  
  129.                             obj.uploadProgressBar.updateText("");  
  130.  
  131.                             obj.uploadAction[0].enable();  
  132.  
  133.                             obj.uploadAction[1].disable();  
  134.  
  135.                             obj.uploadAction[2].disable();  
  136.  
  137.                             obj.uploadAction[3].disable();  
  138.  
  139.                      }}),  
  140.  
  141.                      new Ext.Action({text:'上传',disabled:true,handler:function(){  
  142.  
  143.                             var obj=Application.uploadDialog;  
  144.  
  145.                             obj.uploadAction[0].disable();  
  146.  
  147.                             obj.uploadAction[1].disable();  
  148.  
  149.                             obj.uploadAction[2].disable();  
  150.  
  151.                             obj.uploadAction[3].disable();  
  152.  
  153.                             obj.uploadAction[4].disable();  
  154.  
  155.                             var store=obj.uploadGrid.store;  
  156.  
  157.                             var len=store.getCount();  
  158.  
  159.                             var classid=obj.classCombo.getValue();  
  160.  
  161.                             obj.swfu.setPostParams({'classid':classid});  
  162.  
  163.                             obj.swfu.startUpload();  
  164.  
  165.                      }}),  
  166.  
  167.                      new Ext.Action({text:'关闭',handler:function(){  
  168.  
  169.                             Application.uploadDialog.hide();  
  170.  
  171.                      }}),  
  172.  
  173.               ],  
  174.  
  175.    
  176.  
  177.               initDialog:function(){  
  178.  
  179.                      this.classCombo=new Ext.form.ComboBox({  
  180.  
  181.                             hiddenName:'classid',name'classid_name',valueField:"id",displayField:"text",mode:'local',  
  182.  
  183.                             store:this.classStore,blankText:'请选择类别',emptyText:'请选择类别',editable:true,anchor:'90%' 
  184.  
  185.                      })  
  186.  
  187.                        
  188.  
  189.                      this.swfu=new SWFUpload({  
  190.  
  191.                             upload_url:"upload.asp",  
  192.  
  193.                 
  194.  
  195.                             file_size_limit : "102400",        
  196.  
  197.                             file_types : "*.jpg;*.gif",  
  198.  
  199.                             file_types_description : "图片文件(*.jpg,*.gif)",  
  200.  
  201.                             file_upload_limit : "30",  
  202.  
  203.                 
  204.  
  205.                             file_dialog_start_handler : this.fileDialogStart,  
  206.  
  207.                             file_queued_handler : this.fileQueued,            
  208.  
  209.                             file_queue_error_handler : this.uploadError,  
  210.  
  211.                             file_dialog_complete_handler : this.fileDialogComplete,  
  212.  
  213.                             upload_start_handler : this.uploadFileStar,  
  214.  
  215.                             upload_progress_handler : this.uploadProgress,  
  216.  
  217.                             upload_error_handler : this.uploadError,  
  218.  
  219.                             upload_complete_handler : this.uploadQueueComplete,  
  220.  
  221.                             file_complete_handler : this.uploadFileComplete,  
  222.  
  223.                                             
  224.  
  225.                             flash_url:"swfupload.swf",  
  226.  
  227.                 
  228.  
  229.                             ui_container_id : "SWFUploadTarget",  
  230.  
  231.                             degraded_container_id : "divDegraded",  
  232.  
  233.                             debug: false 
  234.  
  235.                      })  
  236.  
  237.                        
  238.  
  239.                      this.dialog=new Ext.Window({  
  240.  
  241.              layout:'fit',width:600,height:500,title:'上传图片',closeAction:'hide',border:false,modal:true,  
  242.  
  243.              plain:true,closable:false,resizable:false,  
  244.  
  245.                             bbar:[this.uploadProgressBar=new Ext.ProgressBar({width:586})],  
  246.  
  247.              items:[  
  248.  
  249.                  Application.uploadDialog.uploadGrid=new Ext.grid.GridPanel({  
  250.  
  251.                         autoExpandColumn:2,enableHdMenu:false,  
  252.  
  253.                                           tbar:[Application.uploadDialog.uploadAction[0],Application.uploadDialog.uploadAction[1],Application.uploadDialog.uploadAction[2],  
  254.  
  255.                                           '-',Application.uploadDialog.uploadAction[3],"-",Application.uploadDialog.classCombo,"->" 
  256.  
  257.                                           ,Application.uploadDialog.uploadAction[4]],  
  258.  
  259.                                           bbar:[Application.uploadDialog.stateInfo=new Ext.Toolbar.TextItem(String.format(Application.uploadDialog.statuBarText,0,Ext.util.Format.fileSize(0)))],  
  260.  
  261.                            store: new Ext.data.SimpleStore({fields: ["id","state""file","size","type"],data:[]}),  
  262.  
  263.                            columns:[  
  264.  
  265.                               new Ext.grid.RowNumberer(),  
  266.  
  267.                              {id:'id',header: "id",hidden:true,width:150,dataIndex:'id',resizable:false,sortable:false},  
  268.  
  269.                              {header: "文件名",width:Ext.grid.GridView.autoFill,dataIndex:'file',sortable:true},  
  270.  
  271.                              {header: "大小", width: 80,renderer:Ext.util.Format.fileSize,dataIndex:'size',sortable:true,align:'right'},  
  272.  
  273.                              {header: "类型", width: 80,dataIndex:'type',align:'center',sortable:true},  
  274.  
  275.                              {header: "状态", width: 100,dataIndex:'state',align:'center',sortable:true}  
  276.  
  277.                            ]  
  278.  
  279.                                    })  
  280.  
  281.                             ]  
  282.  
  283.                      })  
  284.  
  285.               },  
  286.  
  287.    
  288.  
  289.               fileQueued:function(file){  
  290.  
  291.                      var obj=Application.uploadDialog;  
  292.  
  293.                      var filetype=(file.type.substr(1)).toUpperCase();  
  294.  
  295.                      if(filetype=='JPG' | filetype=='GIF'){  
  296.  
  297.                             var data=[];  
  298.  
  299.                             data.push([file.id,'未上传',file.name,file.size,filetype]);  
  300.  
  301.                             obj.uploadGrid.store.loadData(data,true);  
  302.  
  303.                             obj.uploadAction[1].enable();  
  304.  
  305.                             obj.uploadAction[2].enable();  
  306.  
  307.                             obj.uploadAction[3].enable();  
  308.  
  309.                             obj.stateInfo.getEl().innerHTML=String.format(obj.statuBarText,obj.uploadGrid.store.getCount(),Ext.util.Format.fileSize(obj.uploadGrid.store.sum('size')));  
  310.  
  311.                      }  
  312.  
  313.               },  
  314.  
  315.                        
  316.  
  317.               uploadFileStar:function(file){  
  318.  
  319.                      var obj=Application.uploadDialog;  
  320.  
  321.                      var index=obj.findData(file.id);  
  322.  
  323.                      if(index>=0){  
  324.  
  325.                             obj.uploadGrid.store.getAt(index).set('state','正在上传……');  
  326.  
  327.                      }  
  328.  
  329.                      obj.uploadProgressBar.updateProgress(0,String.format(obj.progressBarText,file.name,0));  
  330.  
  331.                      return true;  
  332.  
  333.               },  
  334.  
  335.          
  336.  
  337.                        
  338.  
  339.               uploadProgress:function(file,bytesloaded){  
  340.  
  341.                      var obj=Application.uploadDialog  
  342.  
  343.                      var percent = Math.ceil((bytesloaded / file.size) * 100);  
  344.  
  345.                      obj.uploadProgressBar.updateProgress(percent/100,String.format(obj.progressBarText,file.name,percent));  
  346.  
  347.               },  
  348.  
  349.                        
  350.  
  351.               uploadFileComplete:function(file){  
  352.  
  353.                      var obj=Application.uploadDialog;  
  354.  
  355.                      var index=obj.findData(file.id);  
  356.  
  357.                      if(index>=0){  
  358.  
  359.                             obj.uploadGrid.store.getAt(index).set('state','已上传');  
  360.  
  361.                      }  
  362.  
  363.                      if(obj.swfu.getStats().files_queued>0)  
  364.  
  365.                             obj.swfu.startUpload();  
  366.  
  367.               },  
  368.  
  369.                        
  370.  
  371.               uploadFileCancelled:function(file, queuelength){  
  372.  
  373.               },  
  374.  
  375.                        
  376.  
  377.               uploadQueueComplete:function(file,server_data){  
  378.  
  379.                      console.log(server_data);  
  380.  
  381.                      if(server_data=='ok'){  
  382.  
  383.                             var obj=Application.uploadDialog;  
  384.  
  385.                             obj.uploadProgressBar.updateProgress(1,'完成上传');                 
  386.  
  387.                             obj.uploadAction[2].enable();  
  388.  
  389.                             obj.uploadAction[4].enable();  
  390.  
  391.                      }else{  
  392.  
  393.                             alert(server_data);  
  394.  
  395.                      }  
  396.  
  397.               },  
  398.  
  399.          
  400.  
  401.               uploadError:function(file,errcode,msg){  
  402.  
  403.                      var index=Application.uploadDialog.findData(file.id);  
  404.  
  405.                      if(index>=0)  
  406.  
  407.                             Application.uploadDialog.uploadGrid.store.getAt(index).set('state','上传失败');  
  408.  
  409.                      //alert(errcode+','+file.name+','+msg)  
  410.  
  411.               },  
  412.  
  413.                        
  414.  
  415.               uploadCancel:function(file, queuelength){  
  416.  
  417.                      var index=Application.uploadDialog.findData(file.id);  
  418.  
  419.                      if(index>=0)  
  420.  
  421.                             Application.uploadDialog.uploadGrid.store.getAt(index).set('state','取消上传');  
  422.  
  423.               },  
  424.  
  425.                 
  426.  
  427.               fileDialogStart:function(){  
  428.  
  429.               },  
  430.  
  431.                 
  432.  
  433.               fileDialogComplete:function (num_files_queued){  
  434.  
  435.               },  
  436.  
  437.                 
  438.  
  439.               findData:function(id){  
  440.  
  441.                      var rowindex=Application.uploadDialog.uploadGrid.store.find('id',id);  
  442.  
  443.                      return rowindex;  
  444.  
  445.               }  
  446.  
  447.    
  448.  
  449.        }//Application.uploadDialog  

在文件里我先定义了一个Application 对象(Application={}),对象为JSON结构,主要方便将应用的各个功能模块作为Application的一个子对象,方便未来调用与区分。当然了,如果你不喜欢的话可以不要这个,不过这文件就要修改不少东西(:))。

接着我定义了Application的子对象uploadDialog(Application.uploadDialog),改对象主要两个方法是show和hide。
在show方法里可以传入下拉对话框的数据。在show方法里我们首先判断对话框是否已初始化(if(!this.dialog)),如果还没初始化就初始化对话框(this.initDialog())。初始化之后我们就在下来对话框里加载数据(this.classStore.loadData(data)),这个加载方法可参考我的另一片文章《Ext2.0本地模式动态修改combobox选择项》。然后就是设置一下按钮的开关属性,最后是显示对话框。
hide方法主要是关闭对话框了。
我们接着看初始化对话框这函数。
函数第一部是创建了一个下拉对话框并将用uploadDialog的子对象classCombo记录下该对象方便操作。下拉对话框的定义请参考我的文章《Ext2.0 form实例》。这里要注意的是我已经定义了一个下拉对话框的数据存储对象classStore,直接定义给下拉对话框的store属性就行了。
接着定义了一个SWFUpload的对象,该SWFUpload对象用的是“SWFUpload 0.8.3 Revision 7.0 by Jacob Roberts”版本,本来想用最新版本的,但是还没找到怎么传递参数的办法(我要传递图片类别参数),所以放弃了,用回旧版。SWFUpload的使用我们要注意的就是要预先在页面放置两个div容易让SWFUpload加入嵌入swf的代码。我是在页面底部加入两个隐藏的div:
  
  
  
  
  1. <div id="SWFUploadTarget"  style="height:0px;width:0px;disply:none;z-index:-1"></div>  
  2.  
  3. <div id="divDegraded" style="height:0px;width:0px;disply:none;z-index:-2"></div>  

 

这里要注意的就是ui_container_id和degraded_container_id 对象的div的id不能错,呵呵。
flash_url对应的是swf文件的位置,改位置是相对于页面文件的位置,我为了方便,就放在同一目录,不然调这个挺烦的,老是因位置不对而出现错误。upload_url对应的是后台接收文件,其位置是相对于swf文件的位置,千万别搞错了。呵呵,还是放在同目录好,不用考虑路径。
因为我后台是用aspuoload组件的,所以不用考虑file_post_name属性,如果你是用php或其它后台语言,需要通过提交变量名获取文件数据则需要定义这个属性。例如php,定义file_post_name为Filedata,然后在后台通过“$_FILES["Filedata"]”提取数据。
在这个对话框里我限制了上传文件的大小最多是2M(file_size_limit : "2048"),文件类型是jpg或gif文件(file_types : "*.jpg;*.gif"),在选择对话框类型描述里显示图片文件(file_types_description : "图片文件"),一次最多上传30个文件(file_upload_limit : "30")。
下面的就是写句柄的定义了,这里下面会说到,这里就先不说明了。
最后就是定义一个窗口了,用dialog属性来保存这个窗口。窗口我设置成模态显示,不显示关闭按钮,不能改变大小。窗口的底部工具条定义了一个宽度为586的进度条,本来是不用定义的,但是auto的宽度定义,文字居中不能居中,郁闷,不然可以将窗口设置为改变大小的。
在items里就是一个表格面板了,用uploadGrid属性保存了。主要显示5列:行号、文件名、大小、类型和状态,还有一个隐藏列id。行号是Ext2.0新增的一个功能,强,哈哈。使用很简单,在列定义(columns)里将改列定义为“new Ext.grid.RowNumberer()”就行了,简单方便。隐藏列只要设置改列hidden属性为true就行了。文件大小我用了Ext的文件大小格式定义“Ext.util.Format.fileSize”,设置改列的属性renderer为“Ext.util.Format.fileSize”就行了。
为了不让用户通过标题栏的下拉列表将隐藏栏显示出来,我设置了隐藏表格的下拉列表菜单(enableHdMenu:false)。
我在uploadAction里定义了增加、删除、清空、上传、关闭等5个action,然后在表格的的顶部工具栏直接加入这些action就会自动变成按钮了:

 

  
  
  
  
  1. tbar:[Application.uploadDialog.uploadAction[0],Application.uploadDialog.uploadAction[1],Application.uploadDialog.uploadAction[2],  
  2.  
  3.                                           '-',Application.uploadDialog.uploadAction[3],"-",Application.uploadDialog.classCombo,"->"  
  4.  
  5.                                           ,Application.uploadDialog.uploadAction[4]],  

 

感觉是不是有点脱裤子放屁,纯粹多此一举?呵呵。其实不是的,我这样做的主要原因是action可以预先定义,因为不用生成html元件,而且如果你想帮表格加入右键菜单的时候,你可以通过action同时控制toolbar上按钮和右键菜单上的动作,如disbale、enable,而不必分别做操作,而且还有用变量记录这些对象。 如果习惯delphi的开发,应该对action很熟悉了,非常好的一个功能。
在表格底部工具栏放置了一个TextItem,内容是一个格式化的文本“文件总数:{0}个,大小:{1}”。这个格式化文本的定义在文件头部(statuBarText:'文件总数:{0}个,大小:{1}')。通过Ext的string对象将参数替换“{0}”、“{1}”等标记就是正式的显示文本了,是不是很方便?主要代码如下:
  
  
  
  
  1. new Ext.Toolbar.TextItem(String.format(Application.uploadDialog.statuBarText,0,Ext.util.Format.fileSize(0))) 

 

String.format的第一参数就是带标记的字符串,从第二个参数开始从标记“{0}”开始进行替换。
下面我们来看看各个按钮的操作。
增加按钮(uploadAction里面的第一个action)很简单,就是调用SWFUpload的选择文件函数打开文件选择对话框。我在这里用的是多文件选择,如果需要,你可以替换为单文件选择(selectFile)。
删除按钮主要动作就是清除选择行并将SWFUpload对象里文件队列对应的文件设置为取消状态。通过表格的getSelectionModel方法获取一个选择模型,然后通过getSelections方法获取选择行。通过选择行的id(该id是表格自动创建来标识行的)在sotre对象里找到对应的行号(store.indexOfId(selection[i].id)),通过store的getAt方法获取对应的记录。因我们在记录里已经保存了SWFUpload为每个队列文件生成的id,所以我们可以通过SWFUpload的cancelUpload方法在队列中取消该文件的上传(cancelUpload (rec.data.id))。同时在store里删除该记录(store.remove(rec))。最后是更新一下状态行的统计信息和设置一下按钮的状态。
清空按钮主要作用就是清空表格信息和取消所以上传文件队列,操作方法和删除按钮类似。
上传按钮就是屏蔽各按钮,调用SWFUpload的setPostParams方法设置提交参数(setPostParams({'classid':classid})),然后通过startUpload方法开始文件上传。
关闭按钮就是关闭本窗口。
最后就是文件的处理了。
在SWFUpload定义的file_queued_handler句柄在选择文件后产生一个队列时触发,在这个函数里,我们要做的操作就是判断文件的扩展名是否符合要求,然后将数据加入store。加入方法是下来对话框的一样,使用loadData方法,不过要设置第二参数为true,表示是追加而不是覆盖旧的数据。最后是更新按钮状态和统计信息。
upload_start_handler句柄会在文件开始上传时出发。这个函数也没什么特别的地方,就是更新一下状态信息和初始化进度条。进度条的显示文本也使用了一个格式化的字符串。不过这里要注意,“return true”一定要有,不然不会上传文件,会提示错误。
upload_progress_handler句柄不用说就是上传进度了,它有两个参数,第一是文件对象,第二就是已上传的字节数,通过换算就可以获得百分比,然后更新进度条。
file_complete_handler句柄在一个文件上传完成后触发,这里要做的除了更新状态信息外,还要检查SWFUpload文件队列里是否还有要上传的文件,如果有,则继续上传(if(obj.swfu.getStats().files_queued>0) obj.swfu.startUpload();)。
upload_complete_handler句柄在文件全部上传后触发,其操作也是更新状态信息。不过可以通过第二个参数server_data获取后台反馈回来的信息,判断上传结果。
upload_error_handler句柄在文件上传发生错误时触发,这里要做的就是更新文件状态信息为“上传失败”。
还有其它的句柄我就不一一介绍了,大家可以去看相应的文章和例子。我推荐一个网址是 http://swfupload.praxion.co.za/。其实我这个就是通过它这个修改过来的,呵呵。
该对话框的实用性可能不大,不过对大家学习一下Ext我觉得还是不错的例子。例子没有详细测试过,所以有bug在所难免,希望大家谅解!有什么地方不明白的请与我联系,或者有什么改进意见,也请大家给发邮件给我。多谢!
本例子例程请到我在csdn的资源那里找!相当郁闷,每次发布的资源都不能即时找到路径,不知道csdn是否还要通过审核。例子在IIS6、Firefox和装有Apsupload的机器上测试通过。后台程序的保存位置为D盘test目录,按源文件名保存,并将提交的参数写到了一个txt文件里。

例程下载地址:http://download.csdn.net/source/262788

你可能感兴趣的:(工具,图片上传,swfupload,对话框,ext2)