[AS3] – FTP CLIENT – PART II (UPLOAD/DOWNLOAD)

April 23, 2011 at 2:01 AM (Actionscript) (, , , )

In part 2 I’m going to share the code needed to upload/download a file to/from ftp server…this needs to compiled as Adobe AIR
as im using File and FileStream Objects….
Feel free to post your questions/doubts…will try my best to answer you…
you can download the source code here:
Link 1: as3ftp_up_down_demo.zip – 33.6 KB
Link 2: as3ftp_up_down_demo.zip – 33.6 KB

import flash.events.ProgressEvent;
import flash.events.Event;
import flash.net.Socket;
import flash.events.IOErrorEvent;
import flash.errors.IOError;
import flash.filesystem.FileStream;
import flash.filesystem.File;
import flash.utils.ByteArray;
import flash.events.MouseEvent;
msg.text="Wait! Connecting to ftp server!"
//
var ftp_host:String = "ftp.yourserver";
var ftp_port:Number = "ftp port"//usually 21;
var ftp_username:String = "ftp_username";
var ftp_password:String = "ftp_password";
//
//in this demo we will be manually entering the remote servers folder from which upload or download should happen
var remoteFolderStr:String;
var localFolderStr:String ;
var remoteFile:String;
//Socket instance which will be used to connect to ftp server
var s = new Socket(ftp_host,ftp_port);
s.addEventListener(IOErrorEvent.IO_ERROR,onIOERR);
s.addEventListener(ProgressEvent.SOCKET_DATA, onReturnData);
s.addEventListener(Event.CONNECT, onConnectHandler);
//
//Socket instance which will be used to connect to receive data sent by ftp server
var r:Socket = new Socket();
r.addEventListener(ProgressEvent.SOCKET_DATA, onServData);
r.addEventListener(Event.CONNECT, onPasvConn);
r.addEventListener(IOErrorEvent.IO_ERROR,onIOERR);
//For every command the client sends to ftp server the server returns message with return codes
function onReturnData(evt:ProgressEvent)
{
	var d = s.readUTFBytes(s.bytesAvailable);
	trace(d);
	//check here for complete list of return codes and their meaning
	//- http://en.wikipedia.org/wiki/List_of_FTP_server_return_codes

	// the return message will have a 3 digit return code followed by a space and related message
	// if the 3 digit return code is followed by "-" the it will be a multiline message
	//-wait until the line with 3 digit code followed by space is delivered
	if (d.indexOf("220 ") > -1)
	{
		msg.text="Logging in to ftp server!"
		//connected to ftp server send user name to server
		s.writeUTFBytes("USER "+ftp_username+"\n");
		s.flush();
	}
	if (d.indexOf("331 ") > -1)
	{
		//Username accepted now send password to server
		s.writeUTFBytes("PASS "+ftp_password+"\n");
		s.flush();
	}
	if (d.indexOf("230") > -1 && d.indexOf("OK.") > -1)
	{
		msg.text="Log in successful!"
		this.enableUI(true)
		//Password accepted - lets enetr passive mode and retrive a list of files from a directory
		//first enetr passive mode
		//s.writeUTFBytes("PASV \n");
		//s.flush();
		
	}
	var a = d.indexOf('227');
	if (a > -1)
	{
		//Entering passive mode message will be returned along with it details of ip and port address will be returned
		//-we have to connect to that address to receive the data
		//format of the message will be: 227 Entering Passive Mode (209,190,85,253,148,206)
		//the data inside brackets is the ip and port address, first four numbers represent IP and last 2 PORT
		//the port value have to be calculated by multiplying the 5th number with 256 and adding the 6th number to it
		//here in this example IP is 209.190.85.253 , PORT is (148*256)+206 = 38094
		var st = d.indexOf("(",a);
		var en = d.indexOf(")",a);
		var str;
		str = d.substring(st + 1,en);
		var a2 = str.split(",");
		var p1 = a2.pop();
		var p2 = a2.pop();
		var ip:String = a2.join(".");
		var port:int=(p2*256)+(p1*1);
		r.connect(ip, port);
	}
	if (d.indexOf("226 ") > -1)
	{
		//Data Transfer completed
		//s.writeUTFBytes("QUIT \n");
		//s.flush();
		if (process=='download')
		{
			msg.text="DOWNLOAD_COMPLETE"
			
		}
		if (process=='upload')
		{
			msg.text="UPLOAD_COMPLETE"
		}
		dispatchEvent(new Event("dataReceived"))
	}
	if (d.indexOf("221 ") > -1)
	{
		//LOGGED OUT from server 
	}
	//Response code 150 will be sent by server whenever a data connection is established after we send 'PASV' command
	if (d.indexOf("150 ") > -1)
	{
		if (process == 'upload')
		{
			//Once data connection is established we can start sending the data to the server
			startSendingData();
		}
	}
}
function onConnectHandler(evt:Event)
{
	msg.text="CONNECTED TO FTP SERVER!"
	trace("CONNECTED TO FTP SERVER");
	//Client has connected to ftp server
	//you can also send multiple commands at same time like below or send step by step based on return code
	//-!
	//s.writeUTFBytes("USER username\n");
	//s.writeUTFBytes("PASS password\n"); 
	//s.flush();
}//
function onPasvConn(evt:Event):void
{
	trace("CONNECTED TO DATA PORT");
	
	//s.writeUTFBytes("LIST /your/folder/path\n");

	if (process == 'getDirList')
	{
		//To retrive directory listings send following command
		s.writeUTFBytes("LIST "+remoteFolderStr+"\n");
	}
	else if (process=='download')
	{
		//To Download a file send following command
		//RETR is the command followed by a space and path to file in remote server
		s.writeUTFBytes("RETR "+remoteFolderStr+"/"+remoteFile+"\n");
	}
	else if (process=='upload')
	{
		//To Upload a file send following command
		//STOR is the command followed by a space and path wher to store the file in remote server
		//-with the name of the file to be saved as..you can provide any name with extension
		s.writeUTFBytes("STOR "+remoteFolderStr+"/"+localFile.name+"\n");
	}
	s.flush();
}
function onServData(evt:ProgressEvent):void
{
	//DATA RECEIVED FROM SERVER THRO DATA PORT
	var d;
	if (process == 'getDirList')
	{
		d = r.readUTFBytes(r.bytesAvailable);
		trace(d);
	}
	else if (process=='download')
	{
		//As the data connection is established start writing the data to the fileStream
		fileData = new ByteArray();//temporary bytearray object to write the incoming data
		r.readBytes(fileData, 0, r.bytesAvailable);//write data to the temp bytearray
		fileStream.writeBytes(fileData, 0, fileData.bytesAvailable);//now write the bytearray to file stream
		//instead you can directly write the data to file stream drom socket
	}
}
function onIOERR(evt:IOErrorEvent)
{
	trace(evt.errorID+":"+evt.text);
}
function checkForStream():void
{
	//this function is used to check if the incoming data is fully written to the filestream and then close the filestream
	//-even if the ftp server dispatches that the file has been transfered...you application cn be still writing them to the filestream
		if(!r.connected){		
			fileStream.close()
		}else{
			//if the file is still been writing restart the timer
			dtimer.reset()
			dtimer.start()
		}
	
	
}
//
var process:String = "";// variable to store what action is being performed
var writeToStream:Boolean;//not used here
var fileStream:FileStream;// filestream to which upload/dowload data is written
var localFile:File;//local file which it to be uploaded
var localFolder:File;// local folder to which the downloaded file to be stored
var fileData:ByteArray;//temporary bytearray object to write the incoming data
var interval:Number;
var bufferSize:int;
//
function browseToUpload(evt:MouseEvent=null):void
{
	//called to browse and select the file to upload from local system
	var file:File=new File();
	file.browseForOpen("Select File To Upload");
	file.addEventListener(Event.SELECT,onFileUploadSelect);
}
function browseToDownload(evt:MouseEvent=null):void
{
	//called to browse and select the folder in local system to save the downloaded file
	var file:File=new File();
	file.browseForDirectory("Select Download Folder");
	file.addEventListener(Event.SELECT,onFolderSelect);
}
function onFileUploadSelect(evt:Event):void
{
	localFile = File(evt.target);
	upload_file.text = localFile.nativePath;
}
function onFolderSelect(evt:Event):void
{
	localFolder = File(evt.target);
	local_folder.text = localFolder.nativePath;
}
function initUpload(evt:MouseEvent=null):void
{
	//called when upload event is triggered
	if (localFile.exists && remote_folder.text.length)
	{
		this.remoteFolderStr=remote_folder.text
		startUploadProcess();
	}
}
function initDownload(evt:MouseEvent=null):void
{
	//called when download event is triggered
	if (localFolder.exists && remote_file.text.length)
	{
		var rfs:String=remote_file.text
		var rf:Array=rfs.split("/")
		remoteFile=rf.pop()
		
		this.remoteFolderStr=rf.join("/");
		startDownloadProcess();
	}
}
function startUploadProcess():void
{
	//create and open a fileStream
	fileStream=new FileStream();
	fileStream.open(localFile, FileMode.READ);
	process = "upload";
	fileData = new ByteArray();
	//You need to pass this command 'TYPE I' to set data transfer mode as binary
	s.writeUTFBytes("TYPE I\n");
	s.writeUTFBytes("PASV \n");
	s.flush();
}
function startDownloadProcess():void
{
	localFile = localFolder.resolvePath(remoteFile);
	fileStream=new FileStream();
	fileStream.open(localFile, FileMode.WRITE);
	process = "download";
	fileData = new ByteArray();
	s.writeUTFBytes("TYPE I\n");
	s.writeUTFBytes("PASV \n");
	s.flush();
}
function startSendingData():void
{
	interval = setInterval(sendData,300);
}
function sendData():void
{
	//file to be uploaded is sent as binary data
	if (fileStream.bytesAvailable <= 0)
	{
		clearInterval(interval);
		r.close();
		return;
	}
	if (fileStream.bytesAvailable < bufferSize)
	{
		bufferSize = fileStream.bytesAvailable;
	}
	var ba:ByteArray = new ByteArray();
	fileStream.readBytes(ba, 0, bufferSize);
	r.writeBytes(ba, 0, ba.bytesAvailable);
	r.flush();
}
function onDataReceived(evt:Event):void
{
	if(process=='download'){		
		dtimer.start();
	}
}
//UI elements and events
function enableUI(boo):void{
	btn_up.enabled=btn_down.enabled=upload.enabled=download.enabled=boo
}

btn_up.buttonMode=btn_down.buttonMode=upload.buttonMode=download.buttonMode=true;
var dtimer:Timer = new Timer(10,1);
dtimer.addEventListener(TimerEvent.TIMER_COMPLETE,function(){checkForStream();});
this.addEventListener('dataReceived',onDataReceived)
btn_up.addEventListener(MouseEvent.CLICK,browseToUpload);
btn_down.addEventListener(MouseEvent.CLICK,browseToDownload);
upload.addEventListener(MouseEvent.CLICK,initUpload);
download.addEventListener(MouseEvent.CLICK,initDownload);
enableUI(false)
Advertisements

Permalink 25 Comments

%d bloggers like this: