- 浏览: 16427 次
最新评论
使用Flex实现FTP文件上传功能
2011年04月12日
最近需要使用Flex实现Ftp文件上传功能,Google到chuangxin兄弟的blog正好有相应的文章及代码,甚喜,忙收藏并拜读之。
搞明白原理后,实测时却发现几个问题:
1、发送FTP命令时无响应。可以正常连接服务器,但发送登录用户名后便失去响应,一直到连接超时。
解决方法:这问题解决时间最长,Google了一下午才找到解决方法。发送FTP命令时,结束符号应该是\r\n,而不是之前的\r。
2、上传文件尾部数据丢失,文件上传不全。13.5k的测试文件只能上传12k,文件尾部数据丢失。本问题有规律可循,结合代码排查起来比较容易。
解决方法:修改sendData函数内条件判断语句,到达文件尾部时先写数据再退出,而不是直接退出。
3、文件名为中文,则上传后文件名变乱码。
解决方法:发送FTP命令时使用UTF-8编码。
为了看着方便,后面直接贴出修改后的代码。以下内容转自chuangxin的blog,文章地址http://blog.csdn.net/chuangxin/archive/2010/10/10/ 5931986.aspx.代码部分有略微修正。
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; public class FtpFileUpDownload { private var ftpSocket:Socket; private var ftpResponce:String; private var dataSocket:Socket; private var dataResponse:String; private var clientIP:String; private var clientPort:uint; private var canceled:Boolean = false; private var dispatcher:IEventDispatcher; private var fileName:String; private var fileData:ByteArray; private var _isAnonymous:Boolean = false; private var _userName:String; private var _serverIP:String; private var _userPwd:String; private var _userDir:String; private var _serverPort:uint = 21; private var intervalID:int; // public function FtpFileUpDownload(dispatcher:IEventDispatcher) { this.dispatcher = dispatcher; } /** * isAnonymous, FTP 是否允许 匿名访问,默认为false */ public function get isAnonymous():Boolean{ return _isAnonymous; } public function set isAnonymous(value:Boolean):void{ _isAnonymous = value; } public function get userName():String{ return _userName; } public function set userName(value:String):void{ _userName = value; } public function get serverIP():String{ return _serverIP; } public function set serverIP(value:String):void{ _serverIP = value; } public function get userPwd():String{ return _userPwd; } public function set userPwd(value:String):void{ _userPwd = value; } /** * userDir, FTP 用户上传目录 */ public function get userDir():String{ return _userDir; } public function set userDir(value:String):void{ _userDir = value; } public function get serverPort():uint{ return _serverPort; } public function set serverPort(value:uint):void{ _serverPort = value; } /** * upload file, data is null is not allowed. */ public function upload(data:ByteArray, fileName:String):void{ this.fileName = fileName; this.fileData = data; if(data==null){ dispatcher.dispatchEvent(new FileUpDownloadEvent(FileUpDownloadEvent.ERROR,"Dat a is null is not allowed!")); return; } if(!check()) return; connect(); } private function 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; } private function connect():void{ ftpSocket = new Socket(serverIP, serverPort); ftpSocket.addEventListener(ProgressEvent.SOCKET_DA TA, ftpSocketDataHandle); ftpSocket.addEventListener(SecurityErrorEvent.SECU RITY_ERROR,ftpSocketSecurityErrorHandle); ftpSocket.addEventListener(IOErrorEvent.IO_ERROR,f tpIOErrorHandle); } private function ftpIOErrorHandle(evt:IOErrorEvent):void { dispatcher.dispatchEvent(new FileUpDownloadEvent(FileUpDownloadEvent.ERROR,evt. text)); } private function ftpSocketSecurityErrorHandle(evt:SecurityErrorEven t):void { dispatcher.dispatchEvent(new FileUpDownloadEvent(FileUpDownloadEvent.ERROR,evt. text)); } private function dataSocketSecurityErrorHandle(evt:SecurityErrorEve nt):void { dispatcher.dispatchEvent(new FileUpDownloadEvent(FileUpDownloadEvent.ERROR,evt. text)); } //发送ftpsocket ftp 指令 private function sendCommand(arg:String):void { //arg +="\n"; arg +="\r\n"; //只有\n会导致ftp命令无法发送成功,一直等待直至超时 var content:ByteArray = new ByteArray(); content.writeMultiByte(arg,"gb2312"); ftpSocket.writeBytes(content); ftpSocket.flush(); } private function dataIOErrorHandle(evt:IOErrorEvent):void { dispatcher.dispatchEvent(new FileUpDownloadEvent(FileUpDownloadEvent.ERROR,evt. text)); } private function 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 = new Socket(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); } private var curPos:int = 0; private function 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.writeBytes(fileContents,curPos,fileSize -curPos); dataSocket.flush(); //以上部分修改。 dataSocket.close(); clearInterval(intervalID); return; } dataSocket.writeBytes(fileContents,curPos,chunk); dataSocket.flush(); curPos+=chunk; } private function receiveData():void{ var responce:String = dataSocket.readUTFBytes(dataSocket.bytesAvailable) ; trace("dataSocket response: "+responce); } } } FTP文件上传事件代码: package whh.flex.controls.fileupload { import flash.events.Event; public class FileUpDownloadEvent extends Event { public static const ERROR:String = "FILE_UPLOAD_ERROR"; public static const COMPLETED:String = "FILE_UPLOAD_COMPLETED"; public static const CANCEL:String = "FILE_UPLOAD_CANCEL"; // private var _message:String; private var _data:Object; // public function FileUpDownloadEvent(type:String, message:String = null) { super(type,true); this._name = name; this._message = message; } // public function get message():String{ return _message; } public function set message(value:String):void{ _message = value; } } } 则Application中要进行FTP文件上传,可简单codeing为(假设FTPFileUpDownload实例为ftpFile):
ftpFile.upload(fileData, "demo.doc")
当然为了侦听ftp上传是否出错、完成,需要侦听FileUpDownloadEvent的Error和Complete事件。
发表评论
-
The architecture of Flex and Java applications two (Flex 和 Java 应用程序架构 2)
2012-01-20 01:27 526The architecture of Flex and Ja ... -
flex 打印 预览
2012-01-20 01:27 748flex 打印 预览 2011年03 ... -
在Flex Mobile中构建“本地”菜单
2012-01-20 01:27 895在Flex Mobile中构建“本地”菜单 2010年12月 ... -
Flex4中 一个使用Module的例子
2012-01-20 01:27 1050Flex4中 一个使用Module的例子 2011年02月2 ... -
python 常用类库!(转)
2012-01-19 09:17 2351python 常用类库!(转) 2011年01月21日 ... -
2011-10-10program
2012-01-19 09:17 6542011-10-10program 2011年10月10日 ... -
MFC对话框程序基础复习001
2012-01-19 09:17 686MFC对话框程序基础复习001 2011年04月23日 ... -
MFC----对话框(一)
2012-01-19 09:17 796MFC----对话框(一) 2011年0 ... -
vc++ 向其他进程注入代码的三种方法(转)
2012-01-19 09:17 961vc++ 向其他进程注入代码的三种方法(转) 2010年06 ... -
PRO/E配置文件选项
2012-01-17 01:50 840PRO/E配置文件选项 2010年08月08日 PRO/ ... -
一些工具集合
2012-01-17 01:50 732一些工具集合 2010年11月13日 【显示工具】 ... -
qt中文
2012-01-17 01:50 781qt中文 2011年06月09日 QDataStream ... -
装机必备检测软件全集
2012-01-17 01:50 800装机必备检测软件全集 ... -
3D MAX 常见小问题集合三
2012-01-17 01:50 7543D MAX 常见小问题集合三 ... -
FLEX做的网站
2012-01-15 21:01 627FLEX做的网站 2011年05月1 ... -
Flex开源项目网址列表
2012-01-15 21:01 714Flex开源项目网址列表 2011年06月19日 1. ... -
FLEX地图应用教程之一
2012-01-15 21:01 519FLEX地图应用教程之一 2 ... -
flex类网站收集
2012-01-15 21:01 537flex类网站收集 2010年10月22日 1. Fle ... -
用flex开发 google map应用程式
2012-01-15 21:01 764用flex开发 google map应用程式 2009年09 ...
相关推荐
Flex实现Ftp上传功能模块的源码(web应用),实现向FTP上传文件,无需后台语言支持
NULL 博文链接:https://xieronghua246.iteye.com/blog/907395
Flex和Servlet结合使用,文件上传、下载
// 定义文件的上传路径 private String uploadPath = "G://upload/"; // 限制文件的上传大小 private int maxPostSize = 100 * 1024 * 1024; public FileUploadServlet() { super(); } public void ...
flex选择文件,包括上传 ,显示,ftp
数据管理.ppt第21章 XML的处理.ppt第22章 Flex应用程序开发.ppt第23章 Flex应用程序部署.ppt第24章 文件的上传下载.ppt第25章 Mp3播放器.ppt第26章 用户登录.ppt第27章 电子相册.ppt第28章 浏览FTP.ppt第29章 FLV...
第24章 文件的上传下载.ppt 第25章 Mp3播放器.ppt 第26章 用户登录.ppt 第27章 电子相册.ppt 第28章 浏览FTP.ppt 第29章 FLV播放器.ppt 第30章 留言板.ppt 第31章 在线书店系统.ppt ├─Flex与JAVA │ ...
第01章 Flex简介.ppt ...第24章 文件的上传下载.ppt 第25章 Mp3播放器.ppt 第26章 用户登录.ppt 第27章 电子相册.ppt 第28章 浏览FTP.ppt 第29章 FLV播放器.ppt 第30章 留言板.ppt 第31章 在线书店系统.ppt
2008-07-10 10:54 169472 65848 第24章 文件的上传下载.ppt 2008-07-10 10:57 137728 86032 第25章 Mp3播放器.ppt 2008-07-10 11:00 116736 66591 第26章 用户登录.ppt 2008-07-10 11:02 285184 245454 第27章 电子...
使用.ashx文件处理IHttpHandler实现发送文本及二进制数据的方法 制作一个简单的多页Tab功能 一完美的关于请求的目录不存在而需要url重写的解决方案! 在C#中实现MSN消息框的功能 XmlHttp实现无刷新三联动ListBox 鼠标...
SpeedCommander 是一个非常容易使用的文件管理工具!内置两个操作窗口,可以非常容易的对文件进行排序,删除,复制,移动等操作!内置对Zip,CAB等10种压缩格式的完全支持! 支持对压缩文件直接进行搜索,内置的显示工具支持...
SpeedCommander 是一个非常容易使用的文件管理工具!内置两个操作窗口,可以非常容易的对文件进行排序,删除,复制,移动等操作!内置对Zip,CAB等10种压缩格式的完全支持! 支持对压缩文件直接进行搜索,内置的显示工具支持...
1、使用ftp软件上传Upload文件内的所有内容到网站空间 2、将空间的.net版本切换到.net3.5 3、设置空间目录读写权限为:读取与执行、写入,并给予NETWORK SERVICE用户权限 4、修改默认首页设置为:index.htm ...