使用FLEX进行多文件上传和自定义上传信息
在Web应用中上传文件是比较常见的需求,在这里通过一个实际应用向大家介绍一下在Flex下如何进行多文件上传,并在上传文件的同时提供一些自定义描述信息以便数据逻辑处理。
功能需求
首先通过以下界面了解一下需求:
主要功能包括:
1)允许添加多个上传的文件
2)自定义文件标题
3)可以对没上传的或正在上传的文件删除
4)上传过程把窗体隐藏在后台,不影响用户的其他的操作(这个就很简单,把窗体隐藏起来在主界面显示个上进工作按钮就可以了,需要的时候再点击一下查看进度)
定义文件上下传类
Code
package Codes
{
import HFSoftFx.HFSoftCoreFun;
import flash.events.DataEvent;
import flash.events.ProgressEvent;
import flash.net.FileReference;
import flash.net.URLRequest;
public dynamic class UploadFile
{
public static var DEFAULT:int=0;
public static var LOADING:int=1;
public static var COMPLETE:int=2;
public function UploadFile()
{
}
private var mState:int = DEFAULT;
public function get State():int
{
return mState;
}
private var mName:String;
public function get Name():String
{
return mName;
}
public function set Name(value:String):void
{
mName=value;
}
private var mSize:int;
public function get Size():int
{
return mSize;
}
public function set Size(value:int):void
{
mSize = value;
}
private var mLoadSize:int;
public function get LoadSize():int
{
return mLoadSize;
}
public function set LoadSize(value:int):void{
mLoadSize =value;
}
private var mFileRef:FileReference;
public function get FileRef():FileReference
{
return mFileRef;
}
public function set FileRef(value:FileReference):void
{
mFileRef=value;
}
public function Upload(request:URLRequest,complete:Function=null,
progress:Function=null):void{
FileRef.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA,
function(event:DataEvent){
var str:String = event.data.substr(1,event.data.length-1);
var x:XML=new XML(str);
if(x.Exception !='' && x.Exception !=null )
{
HFSoftCoreFun.AlertError(x.Exception);
}
else
{
mState = COMPLETE;
if(complete!=null)
complete();
}
});
FileRef.addEventListener(ProgressEvent.PROGRESS
,function(event:ProgressEvent){
LoadSize=event.bytesLoaded;
Size =event.bytesTotal;
if(progress!=null)
progress();
});
mState= LOADING;
FileRef.upload(request);
}
}
}
package Codes
{
import HFSoftFx.HFSoftCoreFun;
import flash.events.DataEvent;
import flash.events.ProgressEvent;
import flash.net.FileReference;
import flash.net.URLRequest;
public dynamic class UploadFile
{
public static var DEFAULT:int=0;
public static var LOADING:int=1;
public static var COMPLETE:int=2;
public function UploadFile()
{
}
private var mState:int = DEFAULT;
public function get State():int
{
return mState;
}
private var mName:String;
public function get Name():String
{
return mName;
}
public function set Name(value:String):void
{
mName=value;
}
private var mSize:int;
public function get Size():int
{
return mSize;
}
public function set Size(value:int):void
{
mSize = value;
}
private var mLoadSize:int;
public function get LoadSize():int
{
return mLoadSize;
}
public function set LoadSize(value:int):void{
mLoadSize =value;
}
private var mFileRef:FileReference;
public function get FileRef():FileReference
{
return mFileRef;
}
public function set FileRef(value:FileReference):void
{
mFileRef=value;
}
public function Upload(request:URLRequest,complete:Function=null,
progress:Function=null):void{
FileRef.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA,
function(event:DataEvent){
var str:String = event.data.substr(1,event.data.length-1);
var x:XML=new XML(str);
if(x.Exception !='' && x.Exception !=null )
{
HFSoftCoreFun.AlertError(x.Exception);
}
else
{
mState = COMPLETE;
if(complete!=null)
complete();
}
});
FileRef.addEventListener(ProgressEvent.PROGRESS
,function(event:ProgressEvent){
LoadSize=event.bytesLoaded;
Size =event.bytesTotal;
if(progress!=null)
progress();
});
mState= LOADING;
FileRef.upload(request);
}
}
}
类并不复杂只是定义了一些简单的成员,为什么要把类定义成动态呢,主要是为了方便扩展一些属性成员。
这个类的主要方法就是
Code
public function Upload(request:URLRequest,complete:Function=null,
progress:Function=null):void{
FileRef.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA,
function(event:DataEvent){
var str:String = event.data.substr(1,event.data.length-1);
var x:XML=new XML(str);
if(x.Exception !='' && x.Exception !=null )
{
HFSoftCoreFun.AlertError(x.Exception);
}
else
{
mState = COMPLETE;
if(complete!=null)
complete();
}
});
FileRef.addEventListener(ProgressEvent.PROGRESS
,function(event:ProgressEvent){
LoadSize=event.bytesLoaded;
Size =event.bytesTotal;
if(progress!=null)
progress();
});
mState= LOADING;
FileRef.upload(request);
}
public function Upload(request:URLRequest,complete:Function=null,
progress:Function=null):void{
FileRef.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA,
function(event:DataEvent){
var str:String = event.data.substr(1,event.data.length-1);
var x:XML=new XML(str);
if(x.Exception !='' && x.Exception !=null )
{
HFSoftCoreFun.AlertError(x.Exception);
}
else
{
mState = COMPLETE;
if(complete!=null)
complete();
}
});
FileRef.addEventListener(ProgressEvent.PROGRESS
,function(event:ProgressEvent){
LoadSize=event.bytesLoaded;
Size =event.bytesTotal;
if(progress!=null)
progress();
});
mState= LOADING;
FileRef.upload(request);
}
参数request是定义接收文件的URLRequest
参数complete和progress分别是上传成功和上传进度回调方法。
窗体代码
Code
<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" width="628" height="300" title="上传文件" showCloseButton="true" xmlns:net="flash.net.*">
<mx:close>
<![CDATA[
OnWorkingChange();
PopUpManager.removePopUp(this);
]]>
</mx:close>
<mx:Canvas width="100%" height="100%">
<mx:VBox left="10" right="20" verticalAlign="middle" horizontalAlign="center">
<mx:Repeater dataProvider="{mUploadFiles}" id="rp" width="100%" height="100%">
<mx:HBox data="{rp.currentItem}" verticalAlign="middle" height="26" horizontalAlign="center">
<mx:render>
<![CDATA[
var hb:HBox=HBox(event.target);
var pb:ProgressBar= ProgressBar(hb.getChildByName("pb1"));
var uf:UploadFile=UploadFile(hb.data);
pb.setProgress(uf.LoadSize,uf.Size);
]]>
</mx:render>
<mx:Button visible="{rp.currentItem.State!=UploadFile.COMPLETE}" data="{rp.currentIndex}" icon="@Embed(source='http://www.cnblogs.com/Imanges/delete16.png')" width="28">
<mx:click>
<![CDATA[
DeleteUploadItem(int(event.target.data));
]]>
</mx:click>
</mx:Button>
<mx:Label width="180" text="{rp.currentItem.Name}"/>
<mx:TextInput data="{rp.currentItem}" text="{rp.currentItem.Title}" width="206">
<mx:change>
<![CDATA[
event.target.data.Title = event.target.text;
]]>
</mx:change>
</mx:TextInput>
<mx:ProgressBar id="pb1" labelPlacement="center" mode="manual" width="106" fontWeight="normal"/>
</mx:HBox>
<mx:HRule width="100%"/>
</mx:Repeater>
</mx:VBox>
</mx:Canvas>
<mx:ControlBar horizontalAlign="right" verticalAlign="middle">
<mx:Button label="上传">
<mx:click>
<![CDATA[
Upload_File();
]]>
</mx:click>
</mx:Button>
<mx:Button label="确定">
<mx:click>
<![CDATA[
OnWorkingChange();
PopUpManager.removePopUp(this);
]]>
</mx:click>
</mx:Button>
</mx:ControlBar>
<mx:initialize>
<![CDATA[
My=this;
]]>
</mx:initialize>
<mx:Script>
<![CDATA[
import Codes.PopUpEffect;
import mx.core.IFlexDisplayObject;
import mx.managers.PopUpManager;
import mx.controls.ProgressBar;
import Codes.UploadFile;
import Codes.SysConfig;
import flash.net.URLRequest;
import Codes.Untity;
import flash.net.URLVariables;
import flash.net.FileReference;
import HFSoftFx.HFSoftCoreFun;
private var My:IFlexDisplayObject;
[Bindable]
private var mUploadFiles:Array=new Array();
private var intervalId:uint;
public var WorkingChange:Function;
private function OnWorkingChange():void{
if(WorkingChange!=null)
WorkingChange();
}
public function get UploadFiles():Array
{
return mUploadFiles;
}
private function DeleteUploadItem(index:int)
{
var item:UploadFile = UploadFile(mUploadFiles[index]);
item.FileRef.cancel();
mUploadFiles.splice(index,1);
OnWorkingChange();
rp.executeBindings(true);
if(mUploadFiles.length==0)
PopUpEffect.Hide(My);
}
public function Upload_File():void{
var item:UploadFile = UploadFile(mUploadFiles[0]);
var request:URLRequest = Untity.GetUploadFileRequest();
var variables:URLVariables=new URLVariables();
variables.Title = item.Title;
variables.FolderID = item.FolderID;
request.data=variables;
item.Upload(request,function(){
DeleteUploadItem(0);
if(mUploadFiles.length>0)
intervalId=flash.utils.setInterval(function(){
flash.utils.clearInterval(intervalId);
Upload_File();
},500,null);
},function(){
rp.executeBindings(true);
});
}
public function AddItem(files:FileReferenceList,folderid:int):void{
var item:UploadFile;
var fr:FileReference;
for (var i:uint = 0; i < files.fileList.length; i++) {
fr = FileReference(files.fileList[i]);
if(fr.size>SysConfig.ImageMaxSize)
{
HFSoftCoreFun.AlertError(fr.name+"文件大于"+(SysConfig.ResourceFileMaxSize/1024)+"(KB)");
break;
}
item =new UploadFile();
item.FileRef = fr;
item.FolderID=folderid;
item.Title = fr.name;
item.Name= fr.name;
item.Size = fr.size;
mUploadFiles.push(item);
}
rp.executeBindings(true);
}
]]>
</mx:Script>
</mx:TitleWindow>
<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" width="628" height="300" title="上传文件" showCloseButton="true" xmlns:net="flash.net.*">
<mx:close>
<![CDATA[
OnWorkingChange();
PopUpManager.removePopUp(this);
]]>
</mx:close>
<mx:Canvas width="100%" height="100%">
<mx:VBox left="10" right="20" verticalAlign="middle" horizontalAlign="center">
<mx:Repeater dataProvider="{mUploadFiles}" id="rp" width="100%" height="100%">
<mx:HBox data="{rp.currentItem}" verticalAlign="middle" height="26" horizontalAlign="center">
<mx:render>
<![CDATA[
var hb:HBox=HBox(event.target);
var pb:ProgressBar= ProgressBar(hb.getChildByName("pb1"));
var uf:UploadFile=UploadFile(hb.data);
pb.setProgress(uf.LoadSize,uf.Size);
]]>
</mx:render>
<mx:Button visible="{rp.currentItem.State!=UploadFile.COMPLETE}" data="{rp.currentIndex}" icon="@Embed(source='http://www.cnblogs.com/Imanges/delete16.png')" width="28">
<mx:click>
<![CDATA[
DeleteUploadItem(int(event.target.data));
]]>
</mx:click>
</mx:Button>
<mx:Label width="180" text="{rp.currentItem.Name}"/>
<mx:TextInput data="{rp.currentItem}" text="{rp.currentItem.Title}" width="206">
<mx:change>
<![CDATA[
event.target.data.Title = event.target.text;
]]>
</mx:change>
</mx:TextInput>
<mx:ProgressBar id="pb1" labelPlacement="center" mode="manual" width="106" fontWeight="normal"/>
</mx:HBox>
<mx:HRule width="100%"/>
</mx:Repeater>
</mx:VBox>
</mx:Canvas>
<mx:ControlBar horizontalAlign="right" verticalAlign="middle">
<mx:Button label="上传">
<mx:click>
<![CDATA[
Upload_File();
]]>
</mx:click>
</mx:Button>
<mx:Button label="确定">
<mx:click>
<![CDATA[
OnWorkingChange();
PopUpManager.removePopUp(this);
]]>
</mx:click>
</mx:Button>
</mx:ControlBar>
<mx:initialize>
<![CDATA[
My=this;
]]>
</mx:initialize>
<mx:Script>
<![CDATA[
import Codes.PopUpEffect;
import mx.core.IFlexDisplayObject;
import mx.managers.PopUpManager;
import mx.controls.ProgressBar;
import Codes.UploadFile;
import Codes.SysConfig;
import flash.net.URLRequest;
import Codes.Untity;
import flash.net.URLVariables;
import flash.net.FileReference;
import HFSoftFx.HFSoftCoreFun;
private var My:IFlexDisplayObject;
[Bindable]
private var mUploadFiles:Array=new Array();
private var intervalId:uint;
public var WorkingChange:Function;
private function OnWorkingChange():void{
if(WorkingChange!=null)
WorkingChange();
}
public function get UploadFiles():Array
{
return mUploadFiles;
}
private function DeleteUploadItem(index:int)
{
var item:UploadFile = UploadFile(mUploadFiles[index]);
item.FileRef.cancel();
mUploadFiles.splice(index,1);
OnWorkingChange();
rp.executeBindings(true);
if(mUploadFiles.length==0)
PopUpEffect.Hide(My);
}
public function Upload_File():void{
var item:UploadFile = UploadFile(mUploadFiles[0]);
var request:URLRequest = Untity.GetUploadFileRequest();
var variables:URLVariables=new URLVariables();
variables.Title = item.Title;
variables.FolderID = item.FolderID;
request.data=variables;
item.Upload(request,function(){
DeleteUploadItem(0);
if(mUploadFiles.length>0)
intervalId=flash.utils.setInterval(function(){
flash.utils.clearInterval(intervalId);
Upload_File();
},500,null);
},function(){
rp.executeBindings(true);
});
}
public function AddItem(files:FileReferenceList,folderid:int):void{
var item:UploadFile;
var fr:FileReference;
for (var i:uint = 0; i < files.fileList.length; i++) {
fr = FileReference(files.fileList[i]);
if(fr.size>SysConfig.ImageMaxSize)
{
HFSoftCoreFun.AlertError(fr.name+"文件大于"+(SysConfig.ResourceFileMaxSize/1024)+"(KB)");
break;
}
item =new UploadFile();
item.FileRef = fr;
item.FolderID=folderid;
item.Title = fr.name;
item.Name= fr.name;
item.Size = fr.size;
mUploadFiles.push(item);
}
rp.executeBindings(true);
}
]]>
</mx:Script>
</mx:TitleWindow>
窗体有两个主要方法:
通过FileReferenceList把选择的文件添加到窗体列中
Code
public function AddItem(files:FileReferenceList,folderid:int):void{
var item:UploadFile;
var fr:FileReference;
for (var i:uint = 0; i < files.fileList.length; i++) {
fr = FileReference(files.fileList[i]);
if(fr.size>SysConfig.ImageMaxSize)
{
HFSoftCoreFun.AlertError(fr.name+"文件大于"+(SysConfig.ResourceFileMaxSize/1024)+"(KB)");
break;
}
item =new UploadFile();
item.FileRef = fr;
item.FolderID=folderid;
item.Title = fr.name;
item.Name= fr.name;
item.Size = fr.size;
mUploadFiles.push(item);
}
rp.executeBindings(true);
}
public function AddItem(files:FileReferenceList,folderid:int):void{
var item:UploadFile;
var fr:FileReference;
for (var i:uint = 0; i < files.fileList.length; i++) {
fr = FileReference(files.fileList[i]);
if(fr.size>SysConfig.ImageMaxSize)
{
HFSoftCoreFun.AlertError(fr.name+"文件大于"+(SysConfig.ResourceFileMaxSize/1024)+"(KB)");
break;
}
item =new UploadFile();
item.FileRef = fr;
item.FolderID=folderid;
item.Title = fr.name;
item.Name= fr.name;
item.Size = fr.size;
mUploadFiles.push(item);
}
rp.executeBindings(true);
}
对列表文件进行上传,更新窗体内容。
Code
public function Upload_File():void{
var item:UploadFile = UploadFile(mUploadFiles[0]);
var request:URLRequest = Untity.GetUploadFileRequest();
var variables:URLVariables=new URLVariables();
variables.Title = item.Title;
variables.FolderID = item.FolderID;
request.data=variables;
item.Upload(request,function(){
DeleteUploadItem(0);
if(mUploadFiles.length>0)
intervalId=flash.utils.setInterval(function(){
flash.utils.clearInterval(intervalId);
Upload_File();
},500,null);
},function(){
rp.executeBindings(true);
});
}
public function Upload_File():void{
var item:UploadFile = UploadFile(mUploadFiles[0]);
var request:URLRequest = Untity.GetUploadFileRequest();
var variables:URLVariables=new URLVariables();
variables.Title = item.Title;
variables.FolderID = item.FolderID;
request.data=variables;
item.Upload(request,function(){
DeleteUploadItem(0);
if(mUploadFiles.length>0)
intervalId=flash.utils.setInterval(function(){
flash.utils.clearInterval(intervalId);
Upload_File();
},500,null);
},function(){
rp.executeBindings(true);
});
}
上传的方法很简单就是从0索引开始上传,把上传完成的文件移走继续上传下一个直到列表上传完成,如果现在继添加上传文件也会排到队列后等待上传。
不过实际情况你可以同时上传多个的,只要对不同UploadFile调用Upload即可。
服务端代码
对于采用什么样的服务端来完成文件处理就根据自己的喜好了,我用的是自己基于C#编写的http xml服务。
Code
[ActionMapper]
public class FileUpload:Users.WebService.ActionBase
{
public string Title
{
get;
set;
}
public NClay.File File
{
get;
set;
}
public int FolderID
{
get;
set;
}
protected override void OnExecute()
{
base.OnExecute();
Expression exp = Folder.folderID == FolderID & Folder.owner != Loginer.UserID;
if (Folder.Count(exp) > 0)
throw new Exception("无权在其他人的文件夹中添加文件!");
string filename = Guid.NewGuid().ToString() + System.IO.Path.GetExtension(File.Name);
Files.File f = new File();
f.Owner = Loginer.UserID;
f.OwnerName = Loginer.UserName;
f.FileName = filename;
f.CreateDate = DateTime.Now;
f.Title = Title;
f.FolderID = FolderID;
f.DownloadName = System.IO.Path.GetFileNameWithoutExtension(Title) + System.IO.Path.GetExtension(File.Name);
f.Save();
FileHandler.SaveFile(Loginer.UserName, f.FileName, File);
}
protected override bool SigninAccess
{
get
{
return true;
}
}
}
[ActionMapper]
public class FileUpload:Users.WebService.ActionBase
{
public string Title
{
get;
set;
}
public NClay.File File
{
get;
set;
}
public int FolderID
{
get;
set;
}
protected override void OnExecute()
{
base.OnExecute();
Expression exp = Folder.folderID == FolderID & Folder.owner != Loginer.UserID;
if (Folder.Count(exp) > 0)
throw new Exception("无权在其他人的文件夹中添加文件!");
string filename = Guid.NewGuid().ToString() + System.IO.Path.GetExtension(File.Name);
Files.File f = new File();
f.Owner = Loginer.UserID;
f.OwnerName = Loginer.UserName;
f.FileName = filename;
f.CreateDate = DateTime.Now;
f.Title = Title;
f.FolderID = FolderID;
f.DownloadName = System.IO.Path.GetFileNameWithoutExtension(Title) + System.IO.Path.GetExtension(File.Name);
f.Save();
FileHandler.SaveFile(Loginer.UserName, f.FileName, File);
}
protected override bool SigninAccess
{
get
{
return true;
}
}
}
实际应用效果图