MDM Zinc – FTP Manager

Hello.
This is a class I’ve done long time ago. I’m quite sure it will be helpfull to some people (at least one, the one who sent me an email asking for this class ;) ).

First the class:
[as]
/*
* Class written by Xavier MARTIN (xxlm or zeflasher)
* http://dev.webbymx.net
* http://www.webbymx.net
* If you are using this class, I will be glad to receive a postcard of your place :)
* To do so please visit http://dev.webbymx.net and go in the about page do get my details…
*/
import mdm.*;
// for the delegate class inside
import com.bourre.commands.*;
// log event
import com.bourre.log.*;
import com.bourre.utils.LuminicTracer;

import net.webbymx.zinc.DateManager;
import net.webbymx.zinc.FileSystemManager;

dynamic class net.webbymx.zinc.FTPManager {
/******************************************************************************
* PRIVATE VARIABLES
******************************************************************************/
// EventDisptacher
private var dispatchEvent:Function;
public var addEventListener:Function;
public var removeEventListener:Function;

// ftp log
private var _ftp_server:String;
private var _ftp_port:String;
private var _ftp_username:String;
private var _ftp_password:String;
private var _ftp_folder:String;

// MDM ftp connection
private var _ftp:mdm.FTP;

// ftp management
private var _ftp_connected:Boolean;
private var _ftp_siInterval:Number;
private var _ftp_row:Number;
private var _ftp_file:Number;

// ftp informations
private var _ftp_localFiles:Array;
private var _ftp_remoteFiles:Array;
private var _ftp_localFile:String;
private var _ftp_remoteFile:String;
private var _ftp_totalBytes:Number;
private var _ftp_currentBytes:Number;
private var _ftp_lastCachedBytes:Number;
private var _ftp_fileTansfered:Boolean;
private var _ftp_localRoot:String;
private var _ftp_start:Boolean;
private var _ftp_root:String;
private var _ftp_actualdir:String;

// Dispatched
public var aborted:Function;
public var busy:Function;
public var connected:Function;
public var dirChanged:Function;
public var dirCreated:Function;
public var dirDeleted:Function;
public var error:Function;
public var fileDeleted:Function;
public var fileReceived:Function;
public var fileRenamed:Function;
public var fileSent:Function;
public var fileTransfered:Function;
public var indexFileReceived:Function;
public var listingDone:Function;
public var loggedIn:Function;
public var quit:Function;
public var ready:Function;
public var resolvedLinks:Function;

public var scanLocalCompleted:Function;
public var scanRemoteCompleted:Function;
public var progress:Function;
public var write:Function;

/******************************************************************************
* CONSTRUCTOR
******************************************************************************/
// FTPManager(server:String, port:String, username:String, pwd:String [,localRoot:String, folder:String])
function FTPManager(server:String, port:String, username:String, pwd:String) {
// dispatching event
mx.events.EventDispatcher.initialize(this);
// FTP events (from zinc)
addEventListener(“aborted”, this);
addEventListener(“busy”, this);
addEventListener(“connected”, this);
addEventListener(“dirChanged”, this);
addEventListener(“dirCreated”, this);
addEventListener(“dirDeleted”, this);
addEventListener(“error”, this);
addEventListener(“fileDeleted”, this);
addEventListener(“fileReceived”, this);
addEventListener(“fileRenamed”, this);
addEventListener(“fileSent”, this);
addEventListener(“fileTransfered”, this);
addEventListener(“indexFileReceived”, this);
addEventListener(“listingDone”, this);
addEventListener(“loggedIn”, this);
addEventListener(“quit”, this);
addEventListener(“ready”, this);
addEventListener(“resolvedLinks”, this);

// FTP events added
addEventListener(“scanLocalCompleted”, this);
addEventListener(“scanRemoteCompleted”, this);
addEventListener(“progress”, this);
addEventListener(“write”, this);

// init variables
_ftp_server = server;
_ftp_port = port;
_ftp_username = username;
_ftp_password = pwd;

_ftp_connected = false;
_ftp_localFiles = new Array();
_ftp_remoteFiles = new Array();
_ftp_localFile = null;
_ftp_remoteFile = null;

// preloader
_ftp_totalBytes = null;
_ftp_currentBytes = null;
_ftp_lastCachedBytes = null;
_ftp_fileTansfered = true;
_ftp_start = true;

if (arguments[4] != undefined && typeof(arguments[4]) == “string”) {
_ftp_localRoot = arguments[4];
if(!mdm.FileSystem.folderExists(_ftp_localRoot)) mdm.FileSystem.makeFolder(_ftp_localRoot);
}
if (arguments[5] != undefined && typeof(arguments[5]) == “string”) _ftp_folder = arguments[5];
else _ftp_folder = “none”;
}

/******************************************************************************
* PRIVATE FUNCTIONS
******************************************************************************/
private function getTransferProgress(Void):Void {
// get bytes transfered
_ftp_currentBytes = _ftp.bytesTransfered;
if (_ftp_fileTansfered == false) {
// if current bytes is not a Number
if (isNaN(_ftp_currentBytes)) return;
if (_ftp_currentBytes != _ftp_lastCachedBytes) {
_ftp_lastCachedBytes = _ftp_currentBytes;
dispatchEvent({type: “progress”, target: this, bytesTransfered:_ftp_currentBytes, totalBytes:_ftp_totalBytes});
} else return;
} else {
_ftp_lastCachedBytes = null;
dispatchEvent({type: “progress”, target: this, bytesTransfered:_ftp_currentBytes, totalBytes:_ftp_totalBytes});
}
}

// dispatch the event write with the string passed in param
private function updateStatus(s:String):Void {
dispatchEvent({type: “write”, target: this, txt:s});
}

// OK
// Event Handler for the FTP
private function ftpEventHandler(event:Object) {
//updateStatus(“\nid: “+event.id+” \nsevent: “+event.type);
//updateStatus(“\nlast server reply: “+_ftp.lastReply);
var eventType:String = String(event.type).toUpperCase();

// ABORTED EVENT
if (eventType == “ABORTED”) {
dispatchEvent({type: “aborted”, target: this});
// nothing
return;
}

// BUSY EVENT
if (eventType == “BUSY”) {
dispatchEvent({type: “busy”, target: this});
// nothing
return;
}

// FTP CONNECTED EVENT
if (eventType == “CONNECTED”) {
dispatchEvent({type: “connected”, target: this});
// nothing
return;
}

// FTP DIR CHANGED EVENT
if (eventType == “DIRCHANGED”) {
// show directory
updateStatus(“\n\n************************************”);
updateStatus(“\nCurrent directory: “+_ftp.currentDir+”\n”);
if (_ftp_start) {
_ftp_start = false;
_ftp_root = _ftp.currentDir;
dispatchEvent({type: “loggedIn”, target: this});
}
return;
}

// FTP DIR CREATED EVENT
if (eventType == “DIRCREATED”) {
dispatchEvent({type: “dirCreated”, target: this});
// show directory
return;
}

// FTP ERROR EVENT
if (eventType == “ERROR”) {
_ftp_fileTansfered = true;
clearInterval(_ftp_siInterval);
var lastError = _ftp.error;
dispatchEvent({type: “error”, target: this});
updateStatus(“\nError details: “+lastError);
return;
}

// FTP FILE DELETED
if (eventType == “FILEDELETED”) {
dispatchEvent({type: “fileDeleted”, target: this});
// show directory
return;
}

// FTP FILE RECEIVED EVENT
if (eventType == “FILERECEIVED”) {
clearInterval(_ftp_siInterval);
_ftp_fileTansfered = true;
getTransferProgress();
dispatchEvent({type: “fileReceived”, target: this});
}

// FTP FILE RENAMED EVENT
if (eventType == “FILERENAMED”) {
clearInterval(_ftp_siInterval);
dispatchEvent({type: “fileRenamed”, target: this});
}

// FTP FILE SENT EVENT
if (eventType == “FILESENT”) {
_ftp_fileTansfered = true;
clearInterval(_ftp_siInterval);
//getTransferProgress();
updateStatus(“\nlocal file: “+_ftp_localFile);
updateStatus(“\nremote file: “+_ftp_remoteFile);
updateStatus(“\ntransfer time: “+_ftp.transferTime);

updateStatus(“\nDone”);

// going to the next file
_ftp_file++;
// if there is no more file to upload for this directory
if (_ftp_file >= _ftp_localFiles[_ftp_row][1].length) {
// going to the next one
_ftp_row++;
// reset file index
_ftp_file = 0;
// if there is still directory
if (_ftp_row < _ftp_localFiles.length) {
var dir:String = _ftp_localFiles[_ftp_row][0];
mdm.Dialogs.prompt("row: "+_ftp_row+", "+_ftp_localFiles[_ftp_row]);
mdm.Dialogs.prompt("dir: "+_ftp.currentDir+"/"+dir);
if (!_ftp.dirExists(dir, mdm.SYNC)) _ftp.makeDir(dir, mdm.SYNC);
var success = _ftp.success;
mdm.Dialogs.prompt(success)
_ftp.refresh(mdm.SYNC);
_ftp.chDir(_ftp.currentDir+"/"+_ftp_localFiles[_ftp_row][0], mdm.SYNC);
mdm.Dialogs.prompt("Current dir: "+_ftp.currentDir);
var success = _ftp.success;
mdm.Dialogs.prompt(success)
uploadNextFile()
} else {
updateStatus("\n\nNo others files to upload");
// endUpdate();
}
} else uploadNextFile();

// check if there is still file to dldl for this dir
return;
}

// FTP FILE TRANSFERED
if (eventType == "FILETRANSFERED") {
clearInterval(_ftp_siInterval);
dispatchEvent({type: "fileTransfered", target: this});
}

// FTP INDEX FILE RECEIVED
if (eventType == "INDEXFILERECEIVED") {
clearInterval(_ftp_siInterval);
dispatchEvent({type: "indexFileReceived", target: this});
}

// FTP LISTING DONE
if (eventType == "LISTINGDONE") {
clearInterval(_ftp_siInterval);
dispatchEvent({type: "listingDone", target: this});
}

// FTP LOGGED EVENT
if (eventType == "LOGGEDIN") {
updateStatus("\nLogged in");

if (_ftp_connected == false) {
_ftp_connected = true;
// switch directory if required
if (_ftp != null && _ftp_folder != "none") {
_ftp.chDir(_ftp_folder, mdm.SYNC);
} else dispatchEvent({type: "loggedIn", target: this});
}
return;
}

// FTP QUIT EVENT
if (eventType == "QUIT") {
dispatchEvent({type: "quit", target: this});
// nothing
return;
}

// FTP READY EVENT
if (eventType == "READY") {
dispatchEvent({type: "ready", target: this});
// nothing
return;
}

// FTP RESOLVED LINKS EVENT
if (eventType == "RESOLVEDLINKS") {
dispatchEvent({type: "resolvedLinks", target: this});
// nothing
return;
}
}

function uploadNextFile(Void):Void {
// get the row [dir, [fileinfo, ...]]
var dir:String = _ftp_localFiles[_ftp_row][0];
mdm.Dialogs.prompt("dir: "+dir+", file: "+dir+_ftp_localFiles[_ftp_row][0]+_ftp_localFiles[_ftp_row][1][_ftp_file][0])
var filesize:Number = mdm.FileSystem.getFileSize(dir+_ftp_localFiles[_ftp_row][0]+_ftp_localFiles[_ftp_row][1][_ftp_file][0]);
updateStatus("\n\nUploading new file");
updateStatus("\n - filename: "+_ftp_localFiles[_ftp_row][1][_ftp_file][0]);
updateStatus("\n - filesize: "+String(Math.round(filesize / 1024 * 100)/100)+" Kb ("+filesize+" Bytes)");
// tweenFileTo = Math.round( (KbUplded+filesize) * 100 / KbToUpld);
// tweening the file bar
// mc_progressbar.mc_file.gotoAndStop(tweenFileTo);
// loading the file
upload(_ftp.currentDir+dir+_ftp_localFiles[_ftp_row][1][_ftp_file][0], dir, _ftp_localFiles[_ftp_row][1][_ftp_file][0], filesize);
}

/******************************************************************************
* PUBLIC FUNCTIONS
******************************************************************************/
function scanFolder(scanTo:String, returnArray:Array):Void {
var rootPath:String;
var dispatch:Boolean = true;

// adding the "/" at the end of the string if not here
if (scanTo.charAt(scanTo.length-1) != "/") scanTo += "/";
rootPath = scanTo;

// changing the directory of the ftp
_ftp.chDir(scanTo, mdm.SYNC);

switch (arguments.length) {
case 5:
// if we are in a recursive call
if (arguments[4] != undefined && typeof(arguments[4]) == 'boolean') dispatch = arguments[4];
case 4:
// if we have scan exception or if we are in a recursive call
if (arguments[3] != undefined && typeof(arguments[3]) == 'object' && arguments[3].length > 0) var exception:Array = arguments[3];
else if (arguments[3] != undefined && typeof(arguments[3]) == ‘boolean’) dispatch = arguments[3];
case 3:
// path to the root
if (arguments[2] != undefined && typeof(arguments[2]) == ‘string’) rootPath = arguments[2];
break;
}

// get all the file of the folder
var tmpFiles:Array = _ftp.getFileList();
for (var i:Number = 0; i tmpFiles[i][1] = DateManager.ftpDate(tmpFiles[i][1]);
}

if (tmpFiles.length > 0) returnArray.push([rootPath, tmpFiles]);

// get all the folder of the folder
var tmpFolder:Array = _ftp.getFolderList();
var allFolder:Array = new Array();
for (var i:Number = 0; i if(tmpFolder[i][0] != "" && tmpFolder[i][0] != "." && tmpFolder[i][0] != "..") allFolder.push(tmpFolder[i][0]);
}

for (var fld:Number = 0; fld if (exception != undefined) {
var found:Boolean = false;
for (var i:Number = 0; i if (allFolder[fld]+"/" == exception[i]) found = true;
}
if (!found) scanFolder(scanTo+allFolder[fld]+"/", returnArray, rootPath+allFolder[fld]+"/", exception, false);
} else scanFolder(scanTo+allFolder[fld]+"/", returnArray, rootPath+allFolder[fld]+"/", false);
}
if (dispatch) {
_ftp.chDir(scanTo, mdm.SYNC);
dispatchEvent({type: "scanRemoteCompleted", target: this});
}
}

public function scanRemoteFolder() {
scanFolder(_ftp.currentDir, _ftp_remoteFiles, "/");
}

public function scanLocalFolder() {
var fs:FileSystemManager = new FileSystemManager();
fs._owner = this;
fs.onScanCompleted = function () {
this._owner.dispatchEvent({type: "scanLocalCompleted", target: this._owner});
}
if (arguments[0] != undefined){
var tmpArray:Array = new Array();
if (typeof(arguments[0]) == 'string' ) tmpArray.push(arguments[0]);
if (typeof(arguments[0]) == 'object' ) tmpArray = arguments[0];
fs.scanFolder(_ftp_localRoot, _ftp_localFiles, "/", tmpArray);
} else fs.scanFolder(_ftp_localRoot, _ftp_localFiles, "/");
}

// connection to the FTP
public function connect() {
updateStatus("\n\nConnecting to FTP...");
if (_ftp == null) {
_ftp = new mdm.FTP(_ftp_server, _ftp_port);
_ftp._owner = this;
// FTP properties
_ftp.transferMode = "binary";
_ftp.async = false;

// EVENTS REFERENCES
_ftp.onAborted = Delegate.create(this, ftpEventHandler);
_ftp.onBusy = Delegate.create(this, ftpEventHandler);
_ftp.onConnected = Delegate.create(this, ftpEventHandler);
_ftp.onDirChanged = Delegate.create(this, ftpEventHandler);
_ftp.onDirCreated = Delegate.create(this, ftpEventHandler);
_ftp.onError = Delegate.create(this, ftpEventHandler);
_ftp.onFileDeleted = Delegate.create(this, ftpEventHandler);
_ftp.onFileReceived = Delegate.create(this, ftpEventHandler);
_ftp.onFileRenamed = Delegate.create(this, ftpEventHandler);
_ftp.onFileSent = Delegate.create(this, ftpEventHandler);
_ftp.onTransfered = Delegate.create(this, ftpEventHandler);
_ftp.onIndexFileReceived = Delegate.create(this, ftpEventHandler);
_ftp.onListingDone = Delegate.create(this, ftpEventHandler);
_ftp.onLoggedIn = Delegate.create(this, ftpEventHandler);
_ftp.onQuit = Delegate.create(this, ftpEventHandler);
_ftp.onReady = Delegate.create(this, ftpEventHandler);
_ftp.onResolvedLinks = Delegate.create(this, ftpEventHandler);

// actual login
_ftp.login(_ftp_username,_ftp_password);
}
}

// changing directory to the one specified (full path)
public function getPath(s:String):Array {
var pathArray:Array = new Array();
pathArray = s.split("/");

var tmpName:Array = new Array();
tmpName = pathArray[pathArray.length-1];

pathArray.splice(pathArray.length-1);
var tmpDir:String = pathArray.join("/");

var finalArray:Array = new Array(tmpName, tmpDir);
return (finalArray);
}

// downloading a file
// arguments[2] -> filesize
public function download(r:String, l:String):Void {

var infos:Array = new Array();
infos = getPath(r);

var linfos:Array = new Array();
linfos = getPath(l);

// if the directory is not the same, changing it
if (_ftp.currentDir != infos[1]) _ftp.chDir(infos[1]);

// creating the folder if it not existing
if (!mdm.FileSystem.folderExists(linfos[1])) mdm.FileSystem.makeFolder(linfos[1]);

updateStatus(“\ndownloading “+infos[0]);
if (r != undefined) {
_ftp_localFile = l;
_ftp_remoteFile = infos[0];
_ftp_totalBytes = _ftp.getFileSize(_ftp_remoteFile);
if (isNaN(_ftp_totalBytes)) {
_ftp_totalBytes == null;
updateStatus(“\nCannot get remote file size”);
return;
}
updateStatus(“\nRemote file size: “+_ftp_totalBytes);
_ftp_fileTansfered = false;
if (_ftp != null) {
_ftp_siInterval = setInterval(this, “getTransferProgress”, 500);
// creating the folder in the ftp folder
_ftp.getFile(_ftp_remoteFile, _ftp_localFile, mdm.ASYNC);
}
} else {
_ftp_fileTansfered = true;
updateStatus(“\nCannot get remote file information”);
}
}

// uploading a file
public function upload(lf:String, rd:String, rf:String, fs:Number):Void {
updateStatus(“\nUploading “+lf);
if (fs != undefined) {
_ftp_localFile = lf;
_ftp_remoteFile = rf;
_ftp_totalBytes = fs;
if (isNaN(_ftp_totalBytes)) {
_ftp_totalBytes == null;
updateStatus(“\nCannot get local file size”);
return;
}
updateStatus(“\nLocal file size: “+_ftp_totalBytes);
_ftp_fileTansfered = false;
if (_ftp != null) {
// creating the folder in the ftp folder
_ftp.sendFile(_ftp_localFile, _ftp_remoteFile, mdm.ASYNC);
}
_ftp_siInterval = setInterval(this, “getTransferProgress”, 500);
} else {
_ftp_fileTansfered = true;
updateStatus(“\nCannot get local file size”);
}
}

public function close(Void):Void {
_ftp.close();
}

/******************************************************************************
* GET & SET
******************************************************************************/
public function get ftp_localFiles():Array {return _ftp_localFiles}
public function get ftp_localFile():String {return _ftp_localFile}
public function set ftp_remoteFiles(a:Array) {_ftp_remoteFiles = a}
public function get ftp_remoteFiles():Array {return _ftp_remoteFiles}
public function get ftp_root():String {return _ftp_root}
public function get local_root():String {return _ftp_localRoot}
public function get ftp():mdm.FTP {return _ftp}
} //END CLASS
[/as]

[Download id not defined]

Check the class. I have no time to provide an example nor to explain how it works. But it’s kinda simple. You have a couple of helpfull public function, and in the ftpEventHandler function you can see that events are dispached. So just create your function like eg
[as]
myftp.fileReceived = function () {
// code here
}
[/as]

I know as well that the way I used to call this function is not good. I could simply reference them in the var declaration and called them in my code and then not dispatching any events. I know. Maybe I will revised this code soon…
Anyway it works this way, so if you wanna use it you can…

Cheers

Tags: , , ,

  • leonardo

    hi, i am very impressed by your work. i get very dizzy with all that code. but i have a question :)
    how i can list the ftp content in a tree component?
    if you can helpme i will be more than pleased.

    thanks.

  • leonardo

    hi, i am very impressed by your work. i get very dizzy with all that code. but i have a question :)
    how i can list the ftp content in a tree component?
    if you can helpme i will be more than pleased.

    thanks.

  • zeflasher

    When scanning the ftp you can have an array of folder. So you jsut need to get this array and have your tree displaying it…
    Check the scanFolder function ( returns an array )
    ++

  • zeflasher

    When scanning the ftp you can have an array of folder. So you jsut need to get this array and have your tree displaying it…
    Check the scanFolder function ( returns an array )
    ++

  • Waldorocko

    Esta clase no me funciona el zinc ahora devuelve otra cadena si el año