Flex FTP文件上传
2010年10月10日
Flex FTP文件上传原理就是利用Flex Socket组件与FTP服务器进行网络通讯并根据FTP协议进行指令发生、接收,数据的传输和接收。本文指的是Flex web应用的FTP文件上传,具体实现有下述3个工作:
1)上传文件选择、加载,可以使用Flex的FileRefrence组件;
2)socket创建、连接、ftp用户登录信息的验证;
3)文件数据发送;
先假设要上传的文件名称为:demo.doc, 该上传的文件内容为fileData,下述为FTP文件上传的核心类。 package fileupload { import flash.events.Event; import flash.events.IEventDispatcher; import flash.events.IOErrorEvent; import flash.events.ProgressEvent; import flash.events.SecurityErrorEvent; import flash.net.FileReference; import flash.net.Socket; import flash.utils.ByteArray; import flash.utils.clearInterval; import flash.utils.setInterval; publicclass FtpFileUpDownload { privatevar ftpSocket:Socket; privatevar ftpResponce:String; privatevar dataSocket:Socket; privatevar dataResponse:String; privatevar clientIP:String; privatevar clientPort:uint; privatevar canceled:Boolean = false; privatevar dispatcher:IEventDispatcher; privatevar fileName:String; privatevar fileData:ByteArray; privatevar _isAnonymous:Boolean = false; privatevar _userName:String; privatevar _serverIP:String; privatevar _userPwd:String; privatevar _userDir:String; privatevar _serverPort:uint = 21; privatevar intervalID:int; // publicfunction FtpFileUpDownload(dispatcher:IEventDispatcher) { this.dispatcher = dispatcher; } /** * isAnonymous, FTP 是否允许匿名访问,默认为false
*/
publicfunctionget isAnonymous():Boolean{
return _isAnonymous;
}
publicfunctionset isAnonymous(value:Boolean):void{
_isAnonymous = value;
}
publicfunctionget userName():String{
return _userName;
}
publicfunctionset userName(value:String):void{
_userName = value;
}
publicfunctionget serverIP():String{
return _serverIP;
}
publicfunctionset serverIP(value:String):void{
_serverIP = value;
}
publicfunctionget userPwd():String{
return _userPwd;
}
publicfunctionset userPwd(value:String):void{
_userPwd = value;
}
/**
* userDir, FTP 用户上传目录
*/
publicfunctionget userDir():String{
return _userDir;
}
publicfunctionset userDir(value:String):void{
_userDir = value;
}
publicfunctionget serverPort():uint{
return _serverPort;
}
publicfunctionset serverPort(value:uint):void{
_serverPort = value;
}
/**
* upload file, data is null is not allowed.
*/
publicfunction upload(data:ByteArray, fileName:String):void{
this.fileName = fileName;
this.fileData = data;
if(data==null){
dispatcher.dispatchEvent(new FileUpDownloadEvent(FileUpDownloadEvent.ERROR,"Data is null is not allowed!"));
return;
}
if(!check()) return;
connect();
}
privatefunction check():Boolean{ var blnResult:Boolean = true; if(!isAnonymous){ if(StringUtil.isEmpty(userName) || StringUtil.isEmpty(userPwd)){// dispatcher.dispatchEvent(new FileUpDownloadEvent(FileUpDownloadEvent.ERROR, "请输入用户名和口令!"));
blnResult = false;
}
}
if(StringUtil.isEmpty(serverIP)){
dispatcher.dispatchEvent(new FileUpDownloadEvent(FileUpDownloadEvent.ERROR,
"请输入FTP服务器IP地址!"));
blnResult = false;
}
return blnResult;
}
privatefunction connect():void{
ftpSocket = newSocket(serverIP, serverPort);
ftpSocket.addEventListener(ProgressEvent.SOCKET_DA TA, ftpSocketDataHandle); ftpSocket.addEventListener(SecurityErrorEvent.SECU RITY_ERROR,ftpSocketSecurityErrorHandle);
ftpSocket.addEventListener(IOErrorEvent.IO_ERROR,f tpIOErrorHandle);
}
privatefunction ftpIOErrorHandle(evt:IOErrorEvent):void {
dispatcher.dispatchEvent(new FileUpDownloadEvent(FileUpDownloadEvent.ERROR,evt. text));
}
privatefunction ftpSocketSecurityErrorHandle(evt:SecurityErrorEven t):void {
dispatcher.dispatchEvent(new FileUpDownloadEvent(FileUpDownloadEvent.ERROR,evt. text));
}
privatefunction dataSocketSecurityErrorHandle(evt:SecurityErrorEve nt):void {
dispatcher.dispatchEvent(new FileUpDownloadEvent(FileUpDownloadEvent.ERROR,evt. text));
}
//发送ftpsocket ftp 指令 privatefunction sendCommand(arg:String):void { arg +="\n"; var content:ByteArray = new ByteArray(); content.writeMultiByte(arg,"gb2312"); ftpSocket.writeBytes(content); ftpSocket.flush(); } privatefunction dataIOErrorHandle(evt:IOErrorEvent):void { dispatcher.dispatchEvent(new FileUpDownloadEvent(FileUpDownloadEvent.ERROR,evt. text)); } privatefunction ftpSocketDataHandle(evt:ProgressEvent):void{ ftpResponce = ftpSocket.readUTFBytes(ftpSocket.bytesAvailable); var serverResponse:String =ftpResponce.substr(0, 3); if(ftpResponce.indexOf('227')>-1){ //取得使用者的ip位置 var temp:Object = ftpResponce.substring(ftpResponce.indexOf("(")+1 ,ftpResponce.indexOf(")")); var upLoadSocket_temp:Object = temp.split(","); clientIP = upLoadSocket_temp.slice(0,4).join("."); clientPort = parseInt(upLoadSocket_temp[4])*256+ int(upLoadSocket_temp[5]); //创建上传的ftp连接 dataSocket = newSocket(clientIP,clientPort); dataSocket.addEventListener(ProgressEvent.SOCKET_D ATA, receiveData); dataSocket.addEventListener(IOErrorEvent.IO_ERROR, dataIOErrorHandle); dataSocket.addEventListener(SecurityErrorEvent.SEC URITY_ERROR,dataSocketSecurityErrorHandle); //upload file sendCommand("STOR "+this.fileName); } switch(serverResponse){ case"150": //开始文件传输 curPos = 0; intervalID = setInterval(sendData,30); break; case"220": //FTP连接就绪 sendCommand("USER "+this.userName); break; case"331"://用户名正确,请继续输入口令 sendCommand("PASS "+this.userPwd); break; case"230"://登入成功 //指定下载文件的类型,I是二进位文件,A是字元文件 sendCommand("TYPE A");//设定TYPE为ASCII sendCommand("TYPE I");//设定上传的编码为8-bit binary if(!StringUtil.isEmpty(userDir)) //设定FTP 上传目录 sendCommand("CWD "+userDir); sendCommand("PASV");//passive模式 break; case"250" ://资料夹切换成功 break; case"226"://关闭数据连接。请求的文件操作成功(比如,文件传输或文件终止) ftpSocket.close(); dispatcher.dispatchEvent(new FileUpDownloadEvent(FileUpDownloadEvent.COMPLETED) ); break; case"227" : //Entering Passive Mode (h1,h2,h3,h4,p1,p2). break; case"530": //530 Login incorrect dispatcher.dispatchEvent(new FileUpDownloadEvent(FileUpDownloadEvent.ERROR,"用户名或者密码有误!"));
break;
case"421":
dispatcher.dispatchEvent(new FileUpDownloadEvent(FileUpDownloadEvent.ERROR,"连接超时!"));
break;
default:
}
trace("ftp response: "+ftpResponce);
}
privatevar curPos:int = 0;
privatefunction sendData():void{
var fileContents:ByteArray =this.fileData;
var fileSize:uint = this.fileData.length;
var chunk:uint = 1024*2; //var pos:int = 0; if(curPos+chunk>fileSize){ dataSocket.close(); clearInterval(intervalID); return; } dataSocket.writeBytes(fileContents,curPos,chunk); dataSocket.flush(); curPos+=chunk; } privatefunction receiveData():void{ var responce:String = dataSocket.readUTFBytes(dataSocket.bytesAvailable) ; trace("dataSocket response: "+responce); } } } FTP文件上传事件代码: package whh.flex.controls.fileupload { import flash.events.Event; publicclassFileUpDownloadEventextends Event { publicstaticconst ERROR:String = "FILE_UPLOAD_ERROR"; publicstaticconst COMPLETED:String = "FILE_UPLOAD_COMPLETED"; publicstaticconst CANCEL:String = "FILE_UPLOAD_CANCEL"; // privatevar _message:String; privatevar _data:Object; // publicfunctionFileUpDownloadEvent(type:String, message:String = null) { super(type,true); this._name = name; this._message = message; } // publicfunctionget message():String{ return _message; } publicfunctionset message(value:String):void{ _message = value; } } } 则Application中要进行FTP文件上传,可简单codeing为(假设FTPFileUpDownload实例为ftpFile):
ftpFile.upload(fileData, "demo.doc")
当然为了侦听ftp上传是否出错、完成,需要侦听FileUpDownloadEvent的Error和Complete事件。
2010年10月10日
Flex FTP文件上传原理就是利用Flex Socket组件与FTP服务器进行网络通讯并根据FTP协议进行指令发生、接收,数据的传输和接收。本文指的是Flex web应用的FTP文件上传,具体实现有下述3个工作:
1)上传文件选择、加载,可以使用Flex的FileRefrence组件;
2)socket创建、连接、ftp用户登录信息的验证;
3)文件数据发送;
先假设要上传的文件名称为:demo.doc, 该上传的文件内容为fileData,下述为FTP文件上传的核心类。 package fileupload { import flash.events.Event; import flash.events.IEventDispatcher; import flash.events.IOErrorEvent; import flash.events.ProgressEvent; import flash.events.SecurityErrorEvent; import flash.net.FileReference; import flash.net.Socket; import flash.utils.ByteArray; import flash.utils.clearInterval; import flash.utils.setInterval; publicclass FtpFileUpDownload { privatevar ftpSocket:Socket; privatevar ftpResponce:String; privatevar dataSocket:Socket; privatevar dataResponse:String; privatevar clientIP:String; privatevar clientPort:uint; privatevar canceled:Boolean = false; privatevar dispatcher:IEventDispatcher; privatevar fileName:String; privatevar fileData:ByteArray; privatevar _isAnonymous:Boolean = false; privatevar _userName:String; privatevar _serverIP:String; privatevar _userPwd:String; privatevar _userDir:String; privatevar _serverPort:uint = 21; privatevar intervalID:int; // publicfunction FtpFileUpDownload(dispatcher:IEventDispatcher) { this.dispatcher = dispatcher; } /** * isAnonymous, FTP 是否允许匿名访问,默认为false
*/
publicfunctionget isAnonymous():Boolean{
return _isAnonymous;
}
publicfunctionset isAnonymous(value:Boolean):void{
_isAnonymous = value;
}
publicfunctionget userName():String{
return _userName;
}
publicfunctionset userName(value:String):void{
_userName = value;
}
publicfunctionget serverIP():String{
return _serverIP;
}
publicfunctionset serverIP(value:String):void{
_serverIP = value;
}
publicfunctionget userPwd():String{
return _userPwd;
}
publicfunctionset userPwd(value:String):void{
_userPwd = value;
}
/**
* userDir, FTP 用户上传目录
*/
publicfunctionget userDir():String{
return _userDir;
}
publicfunctionset userDir(value:String):void{
_userDir = value;
}
publicfunctionget serverPort():uint{
return _serverPort;
}
publicfunctionset serverPort(value:uint):void{
_serverPort = value;
}
/**
* upload file, data is null is not allowed.
*/
publicfunction upload(data:ByteArray, fileName:String):void{
this.fileName = fileName;
this.fileData = data;
if(data==null){
dispatcher.dispatchEvent(new FileUpDownloadEvent(FileUpDownloadEvent.ERROR,"Data is null is not allowed!"));
return;
}
if(!check()) return;
connect();
}
privatefunction check():Boolean{ var blnResult:Boolean = true; if(!isAnonymous){ if(StringUtil.isEmpty(userName) || StringUtil.isEmpty(userPwd)){// dispatcher.dispatchEvent(new FileUpDownloadEvent(FileUpDownloadEvent.ERROR, "请输入用户名和口令!"));
blnResult = false;
}
}
if(StringUtil.isEmpty(serverIP)){
dispatcher.dispatchEvent(new FileUpDownloadEvent(FileUpDownloadEvent.ERROR,
"请输入FTP服务器IP地址!"));
blnResult = false;
}
return blnResult;
}
privatefunction connect():void{
ftpSocket = newSocket(serverIP, serverPort);
ftpSocket.addEventListener(ProgressEvent.SOCKET_DA TA, ftpSocketDataHandle); ftpSocket.addEventListener(SecurityErrorEvent.SECU RITY_ERROR,ftpSocketSecurityErrorHandle);
ftpSocket.addEventListener(IOErrorEvent.IO_ERROR,f tpIOErrorHandle);
}
privatefunction ftpIOErrorHandle(evt:IOErrorEvent):void {
dispatcher.dispatchEvent(new FileUpDownloadEvent(FileUpDownloadEvent.ERROR,evt. text));
}
privatefunction ftpSocketSecurityErrorHandle(evt:SecurityErrorEven t):void {
dispatcher.dispatchEvent(new FileUpDownloadEvent(FileUpDownloadEvent.ERROR,evt. text));
}
privatefunction dataSocketSecurityErrorHandle(evt:SecurityErrorEve nt):void {
dispatcher.dispatchEvent(new FileUpDownloadEvent(FileUpDownloadEvent.ERROR,evt. text));
}
//发送ftpsocket ftp 指令 privatefunction sendCommand(arg:String):void { arg +="\n"; var content:ByteArray = new ByteArray(); content.writeMultiByte(arg,"gb2312"); ftpSocket.writeBytes(content); ftpSocket.flush(); } privatefunction dataIOErrorHandle(evt:IOErrorEvent):void { dispatcher.dispatchEvent(new FileUpDownloadEvent(FileUpDownloadEvent.ERROR,evt. text)); } privatefunction ftpSocketDataHandle(evt:ProgressEvent):void{ ftpResponce = ftpSocket.readUTFBytes(ftpSocket.bytesAvailable); var serverResponse:String =ftpResponce.substr(0, 3); if(ftpResponce.indexOf('227')>-1){ //取得使用者的ip位置 var temp:Object = ftpResponce.substring(ftpResponce.indexOf("(")+1 ,ftpResponce.indexOf(")")); var upLoadSocket_temp:Object = temp.split(","); clientIP = upLoadSocket_temp.slice(0,4).join("."); clientPort = parseInt(upLoadSocket_temp[4])*256+ int(upLoadSocket_temp[5]); //创建上传的ftp连接 dataSocket = newSocket(clientIP,clientPort); dataSocket.addEventListener(ProgressEvent.SOCKET_D ATA, receiveData); dataSocket.addEventListener(IOErrorEvent.IO_ERROR, dataIOErrorHandle); dataSocket.addEventListener(SecurityErrorEvent.SEC URITY_ERROR,dataSocketSecurityErrorHandle); //upload file sendCommand("STOR "+this.fileName); } switch(serverResponse){ case"150": //开始文件传输 curPos = 0; intervalID = setInterval(sendData,30); break; case"220": //FTP连接就绪 sendCommand("USER "+this.userName); break; case"331"://用户名正确,请继续输入口令 sendCommand("PASS "+this.userPwd); break; case"230"://登入成功 //指定下载文件的类型,I是二进位文件,A是字元文件 sendCommand("TYPE A");//设定TYPE为ASCII sendCommand("TYPE I");//设定上传的编码为8-bit binary if(!StringUtil.isEmpty(userDir)) //设定FTP 上传目录 sendCommand("CWD "+userDir); sendCommand("PASV");//passive模式 break; case"250" ://资料夹切换成功 break; case"226"://关闭数据连接。请求的文件操作成功(比如,文件传输或文件终止) ftpSocket.close(); dispatcher.dispatchEvent(new FileUpDownloadEvent(FileUpDownloadEvent.COMPLETED) ); break; case"227" : //Entering Passive Mode (h1,h2,h3,h4,p1,p2). break; case"530": //530 Login incorrect dispatcher.dispatchEvent(new FileUpDownloadEvent(FileUpDownloadEvent.ERROR,"用户名或者密码有误!"));
break;
case"421":
dispatcher.dispatchEvent(new FileUpDownloadEvent(FileUpDownloadEvent.ERROR,"连接超时!"));
break;
default:
}
trace("ftp response: "+ftpResponce);
}
privatevar curPos:int = 0;
privatefunction sendData():void{
var fileContents:ByteArray =this.fileData;
var fileSize:uint = this.fileData.length;
var chunk:uint = 1024*2; //var pos:int = 0; if(curPos+chunk>fileSize){ dataSocket.close(); clearInterval(intervalID); return; } dataSocket.writeBytes(fileContents,curPos,chunk); dataSocket.flush(); curPos+=chunk; } privatefunction receiveData():void{ var responce:String = dataSocket.readUTFBytes(dataSocket.bytesAvailable) ; trace("dataSocket response: "+responce); } } } FTP文件上传事件代码: package whh.flex.controls.fileupload { import flash.events.Event; publicclassFileUpDownloadEventextends Event { publicstaticconst ERROR:String = "FILE_UPLOAD_ERROR"; publicstaticconst COMPLETED:String = "FILE_UPLOAD_COMPLETED"; publicstaticconst CANCEL:String = "FILE_UPLOAD_CANCEL"; // privatevar _message:String; privatevar _data:Object; // publicfunctionFileUpDownloadEvent(type:String, message:String = null) { super(type,true); this._name = name; this._message = message; } // publicfunctionget message():String{ return _message; } publicfunctionset message(value:String):void{ _message = value; } } } 则Application中要进行FTP文件上传,可简单codeing为(假设FTPFileUpDownload实例为ftpFile):
ftpFile.upload(fileData, "demo.doc")
当然为了侦听ftp上传是否出错、完成,需要侦听FileUpDownloadEvent的Error和Complete事件。