FTP File Transfer Using Yii

This tutorials will helpful to transfer the large files (or small files)  from ftp folder to your application folder. When you upload the large files (in applications), It will take some times. But if you use ftp file transfer It will transfer the files fast. Based on my experience i explained below.

Create Ftp Account and Folder

First create a ftp account in your webserver cpanel. Now you have ftp username, ftp password, hosting name and port. This four attributes needed to connect the ftp server from our applications and i gave three files. They are

  1. EFtpComponent (extension)
  2. FilesController (Controller)
  3. index (View file)

Add Ftp Extension

   I gave ftp class source code below (From yii framework site). It contains the basic method of ftp like connect, close, execute, delete, size etc. If you need you can add more functions in this class. Add this class into the folloing path extensions/ftp. Now you created one extension for ftp process.

From yii framework site:

<?php
class EFtpComponent extends CApplicationComponent
{
    /**
     * @var string the host for establishing FTP connection. Defaults to null.
     */
    public $host=null;
    /**
     * @var string the port for establishing FTP connection. Defaults to 21.
     */
    public $port = 21;
    /**
* @var string the username for establishing FTP connection. Defaults to null.
*/
    public $username = null;
    /**
* @var string the password for establishing FTP connection. Defaults to null.
*/
    public $password = null;
    /**
     * @var boolean
     */
    public $ssl = false;
    /**
     * @var string the timeout for establishing FTP connection. Defaults to 90.
     */
    public $timeout = 90;
    /**
* @var boolean whether the ftp connection should be automatically established
* the component is being initialized. Defaults to false. Note, this property is only
* effective when the EFtpComponent object is used as an application component.
*/
public $autoConnect = true;
    private $_active = false;
private $_errors = null;
private $_connection = null;

/**
* @param varchar $host
* @param varchar $username
* @param varchar $password
* @param boolean $ssl
* @param integer $port
* @param integer $timeout
*/
public function __construct($host=null, $username=null, $password=null, $ssl=false, $port=21, $timeout=90)
{
$this->host = $host;
        $this->username = $username;
        $this->password = $password;
        $this->ssl = $ssl;
        $this->port = $port;
        $this->timeout = $timeout;
}
    /**
* Initializes the component.
* This method is required by {@link IApplicationComponent} and is invoked by application
* when the EFtpComponent is used as an application component.
* If you override this method, make sure to call the parent implementation
* so that the component can be marked as initialized.
*/
public function init()
{
parent::init();
if($this->autoConnect)
$this->setActive(true);
}
/**
* @return boolean whether the FTP connection is established
*/
public function getActive()
{
return $this->_active;
}
/**
* Open or close the FTP connection.
* @param boolean whether to open or close FTP connection
* @throws CException if connection fails
*/
public function setActive($value)
{
if($value!=$this->_active)
{
if($value)
$this->connect();
else
$this->close();
}
}
/**
* Connect to FTP if it is currently not
* @throws CException if connection fails
*/
    public function connect()
    {
        if($this->_connection === null){
            // Connect - SSL?
            $this->_connection = $this->ssl ? ftp_ssl_connect($this->host, $this->port, $this->timeout) : ftp_connect($this->host, $this->port, $this->timeout);
            // Connection anonymous?
            if(!empty($this->username) AND !empty($this->password))
            {
                $login_result = ftp_login($this->_connection, $this->username, $this->password);
            } else {
                $login_result = true;
            }
            // Check connection
            if(!$this->_connection)
                throw new CException('FTP Library Error: Connection failed!');
            // Check login
            if((empty($this->username) AND empty($this->password)) AND !$login_result)
                throw new CException('FTP Library Error: Login failed!');
            $this->_active=true;
        }
    }
    /**
* Closes the current FTP connection.
*
* @return boolean
*/
public function close()
{
        if ($this->getActive()){
            // Close the connection
            if(ftp_close($this->_connection))
            {
                return true;
            } else {
                return false;
            }
            $this->_active = false;
            $this->_connection = null;
            $this->_errors = null;
        }
        else{
            throw new CDbException('EFtpComponent is inactive and cannot perform any FTP operations.');
        }
}
/**
* Passed an array of constants => values they will be set as FTP options.
* 
* @param array $config
* @return object (chainable)
*/
public function setOptions($config)
{
        if($this->getActive()){
            if(!is_array($config))
                throw new CException('EFtpComponent Error: The config parameter must be passed an array!');
            // Loop through configuration array
            foreach($config as $key => $value)
            {
                // Set the options and test to see if they did so successfully - throw an exception if it failed
                if(!ftp_set_option($this->_connection, $key, $value))
                    throw new CException('EFtpComponent Error: The system failed to set the FTP option: "'.$key.'" with the value: "'.$value.'"');
            }
            return $this;
        }
        else{
            throw new CDbException('EFtpComponent is inactive and cannot perform any FTP operations.');
        }
}

/**
* Execute a remote command on the FTP server.
* 
* @see  http://us2.php.net/manual/en/function.ftp-exec.php
* @param string remote command
* @return boolean
*/
public function execute($command)
{
        if($this->getActive()){
            // Execute command
            if(ftp_exec($this->_connection, $command))
            {
                return true;
            } else {
                return false;
            }
        }
        else{
            throw new CDbException('EFtpComponent is inactive and cannot perform any FTP operations.');
        }
}

/**
* Get executes a get command on the remote FTP server.
*
* @param string local file
* @param string remote file
* @param const  mode
* @return boolean
*/
public function get($local, $remote, $mode=FTP_BINARY)
{
        if($this->getActive()){
            // Get the requested file
            if(ftp_get($this->_connection, $local, $remote, $mode))
            {
                // If successful, return the path to the downloaded file...
                return $remote;
            } else {
                return false;
            }
        }
        else{
            throw new CDbException('EFtpComponent is inactive and cannot perform any FTP operations.');
        }
}

/**
* Put executes a put command on the remote FTP server.
*
* @param string remote file
* @param string local file
* @param const  mode
* @return boolean
*/
public function put($remote, $local, $mode=FTP_ASCII)
{
        if($this->getActive()){
            // Upload the local file to the remote location specified
            if(ftp_put($this->_connection, $remote, $local, $mode))
            {
                return true;
            } else {
                return false;
            }
        }
        else{
            throw new CDbException('EFtpComponent is inactive and cannot perform any FTP operations.');
        }
}

/**
* Rename executes a rename command on the remote FTP server.
*
* @param string old filename
* @param string new filename
* @return boolean
*/
public function rename($old, $new)
{
        if($this->getActive()){
            // Rename the file
            if(ftp_rename($this->_connection, $old, $new))
            {
                return true;
            } else {
                return false;
            }
        }
        else{
            throw new CDbException('EFtpComponent is inactive and cannot perform any FTP operations.');
        }
}

/**
* Rmdir executes an rmdir (remove directory) command on the remote FTP server.
*
* @param string remote directory
* @return boolean
*/
public function rmdir($dir)
{
        if($this->getActive()){
            // Remove the directory
            if(ftp_rmdir($this->_connection, $dir))
            {
                return true;
            } else {
                return false;
            }
        }
        else{
            throw new CDbException('EFtpComponent is inactive and cannot perform any FTP operations.');
        }
}
    /**
* Mkdir executes an mkdir (create directory) command on the remote FTP server.
*
* @param string remote directory
* @return boolean
*/
    public function mkdir($dir)
    {
        if($this->getActive()){
            // create directory
            if(ftp_mkdir($this->_connection, $dir))
            {
                return true;
            } else {
                return false;
            }
        }
        else{
            throw new CDbException('EFtpComponent is inactive and cannot perform any FTP operations.');
        }
    }
    /**
* Returns the last modified time of the given file
     * Note: Not all servers support this feature!
     * Note: mdtm method does not work with directories.
*
* @param string remote file
* @return mixed Returns the last modified time as a Unix timestamp on success, or false on error.
*/
    public function mdtm($file)
    {
        if($this->getActive()){
            // get the last modified time
            $buff = ftp_mdtm($this->_connection, $file);
            if($buff != -1)
            {
                return $buff;
            } else {
                return false;
            }
        }
        else{
            throw new CDbException('EFtpComponent is inactive and cannot perform any FTP operations.');
        }
    }
/**
* Returns the size of the given file
     * Note: Not all servers support this feature!
*
* @param string remote file
* @return mixed Returns the file size on success, or false on error.
*/
    public function size($file)
    {
        if($this->getActive()){
            // get the size of $file
            $buff = ftp_size($this->_connection, $file);
            if($buff != -1)
            {
                return $buff;
            } else {
                return false;
            }
        }
        else{
            throw new CDbException('EFtpComponent is inactive and cannot perform any FTP operations.');
        }
    }

/**
* Remove executes a delete command on the remote FTP server.
*
* @param string remote file
* @return boolean
*/
public function delete($file)
{
        if($this->getActive()){
            // Delete the specified file
            if(ftp_delete($this->_connection, $file))
            {
                return true;
            } else {
                return false;
            }
        }
        else{
            throw new CDbException('EFtpComponent is inactive and cannot perform any FTP operations.');
        }
}

/**
* Change the current working directory on the remote FTP server.
*
* @param string remote directory
* @return boolean
*/
public function chdir($dir)
{
        if($this->getActive()){
            // Change directory
            if(ftp_chdir($this->_connection, $dir))
            {
                return true;
            } else {
                return false;
            }
        }
        else{
            throw new CDbException('EFtpComponent is inactive and cannot perform any FTP operations.');
        }
}

/**
* Changes to the parent directory on the remote FTP server.
*
* @return boolean
*/
public function parentDir()
{
        if($this->getActive()){
            // Move up!
            if(ftp_cdup($this->_connection))
            {
                return true;
            } else {
                return false;
            }
        }
        else{
            throw new CDbException('EFtpComponent is inactive and cannot perform any FTP operations.');
        }
}

/**
* Returns the name of the current working directory.
*
* @return string
*/
public function currentDir()
{
        if($this->getActive()){
            return ftp_pwd($this->_connection);
        }
        else{
            throw new CDbException('EFtpComponent is inactive and cannot perform any FTP operations.');
        }
}

/**
* Permissions executes a chmod command on the remote FTP server.
*
* @param string remote file
* @param mixed  mode
* @return boolean
*/
public function chmod($file, $mode)
{
        if($this->getActive()){
            // Change the desired file's permissions
            if(ftp_chmod($this->_connection, $mode, $file))
            {
                return true;
            } else {
                return false;
            }
        }
        else{
            throw new CDbException('EFtpComponent is inactive and cannot perform any FTP operations.');
        }
}

/**
* ListFiles executes a nlist command on the remote FTP server, returns an array of file names, false on failure.
*
* @param string remote directory
* @return mixed
*/
public function listFiles($directory)
{
        if($this->getActive()){
            return ftp_nlist($this->_connection, $directory);
        }
        else{
            throw new CDbException('EFtpComponent is inactive and cannot perform any FTP operations.');
        }
}
    
    public function listFileswithdetails($directory)
{
        if($this->getActive()){
            return ftp_rawlist ($this->_connection, $directory);
        }
        else{
            throw new CDbException('EFtpComponent is inactive and cannot perform any FTP operations.');
        }
}

/**
* Close the FTP connection if the object is destroyed.
*
* @return boolean
*/
public function __destruct()
{
return $this->close();
}
}

Config Main.php

'ftp'=>array(
          'class'=>'application.extensions.ftp.EFtpComponent',
          'host'=>'FTP HOST NAME',
          'port'=>21,
          'username'=>'FTP USERNAME',
          'password'=>'FTP PASSWORD',
          'ssl'=>false,
          'timeout'=>90,
          'autoConnect'=>true,
    ),

Add this code into your application “components” of yii framework config/main.php. This is the configuration of ftp account. It contains the hosting name, username, password, ssl, timeout.. Now you will get the “ftp” object of ftp component class.


Ftp Controller

Here i wrote the code for getting the list of ftp files and moving files from ftp to application folder. I wrote two functions for this. They are

  1. actionFtpfilelist
  2. actionMovefileftptoserver

actionFtpfilelist:

This function will help you to retrieve the list of file, directory from your ftp server. Here i filltered the files based on file extensions.

actionMovefileftptoserver:

Using this function you can move multiple files from ftp folder to your application folder. I did this process like copy from ftp and paste into application folder. Once file moved The ftp file will be deleted.

<?php
public $layout='//layouts/column2';
public $FILEDIR="themacro/largefiles";
public function actionIndex(){
$this->render("index");
}

public function actionFtpfilelist($path=''){
$local_file = 'tempnew.zip';
$filetypearray=array('jpg','png','pdf','doc');
$ftp = Yii::app()->ftp;
$currentpath=$this->FILEDIR.$path;
$contents=$ftp->listFiles($currentpath);
$i=0;$j=0;
$filelist=array();
$dirlist=array();
foreach($contents as $item){

if($item!='.' && $item!='..'){
$res=$ftp->size($currentpath.'/'.$item);
if($res) {
$ext = strtolower(substr($item, strrpos($item, '.')+1));
if(in_array($ext, $filetypearray))
{
$filelist[$i]['name']=$item;
$filelist[$i]['dirname']=$path;
$i++;
}
}
else {
$dirlist[$j]['name']=$item;
$dirlist[$j]['dirname']=$path.'/'.$item;
$j++;
}
}
}

$RESULT['FILELIST']=$filelist;
$RESULT['DIRLIST']=$dirlist;
echo json_encode($RESULT);
}

public function actionMovefileftptoserver(){
if(Yii::app()->request->isAjaxRequest){
$currenttime=new CDbExpression('NOW()');
$ftp = Yii::app()->ftp;
$file=$_POST['filepath'];
$fileArray=json_decode(stripslashes($file),true);
$success=0;
foreach($fileArray as $file) {
$filenamearray=explode('/',$file);
$filename=$filenamearray[count($filenamearray)-1];
$path_parts = pathinfo($filename);
$ext=$path_parts['extension'];
$newfilename=rand(11111,99999).time();
$local_file = 'tempnew.zip';
$server_file = $this->FILEDIR.$file;
$size=$ftp->size($server_file);
if ($ftp->get($local_file ,$server_file))
{
$destination=Yii::app()->basePath.'/files/';
$saveas=Yii::app()->basePath.'/files/'.$newfilename.$filename;
if(!is_dir($destination)){
mkdir($destination);
}
if(copy($local_file,$saveas))
{
$filenameerror[]=$filename." Transfered Successfully";
$success=1;
$ftp->delete($server_file);
foreach (glob($local_file) as $del)
{
unlink($del);
}
}else{
$filenameerror[]="Transfer Error For".$filename;
}
}
}
$RESULT['status']=$success;
$RESULT['message']=$filenameerror;
echo json_encode($RESULT);
}
}
}

FTP View

Add index.php file into the ftp folder of view. I gave the view file code. Just copy and paste into your index.php file. Add index.php file into the ftp folder of view. I gave the view file code. Just copy and paste into your index.php file. 

Note: Please add one image inside the “images” folder and image name is  images/ajax-loader.gif.

Click the load button. Now you will get the directory list and files list.

When you click on the directory list you will get the list of files, directory from parent directory.

Click the checkbox of selected files and click the “Move” button. Now the selected files are moved from ftp to application folder.

<?php $url=Yii::app()->createAbsoluteUrl('files/ftpfilelist');
$fileurl=Yii::app()->createAbsoluteUrl('files/movefileftptoserver');
$redirecturl=Yii::app()->createAbsoluteUrl("files");
Yii::app()->clientScript->registerScript('filejs',"
$('#directorydiv a').live('click',function(){

var currenturl=$(this).attr('id');
$.ajax({
url:'$url',
type:'GET',
data:'path='+currenturl,
dataType:'json',
success:function(data){
var result=eval(data);
$.each(result,function(key,value){
if(key=='FILELIST'){
filelistfunction(value);
}else if(key=='DIRLIST'){
directorylistfunction(value);
}

});
lightboxhide();
}
});
lightboxloader();
});
$('#loadbtn').live('click',function(){
$(this).css('display','none');
loadfiles();
});
$('#filemovebtn').live('click',function(){
var filearray=new Array();
var i=0;
$('.filenames').each(function(){
if($(this).is(':checked')){
var filename=$(this).closest('tr').find('a').attr('id');
filearray.push(filename);
i++;
}
});
if(filearray.length>0){
dataArray=JSON.stringify(filearray);
$.ajax({
url:'$fileurl',
type:'POST',
data:'filepath='+dataArray,
dataType:'json',
success:function(data){
var result=eval(data);
var redirect=0;
var messagestring='';
$.each(result,function(key,value){
if(key=='status'){
if(value==1){
redirect=1;
}
}else if(key=='message'){
$.each(value,function(key1,value1){
if(messagestring!=''){
messagestring+=',\\n';
}
messagestring+=value1;
});
}
});
alert(messagestring);
if(redirect==1){
window.location.href='$redirecturl';
}
lightboxhide();
}
});
lightboxloader();
}
});
function lightboxloader(){
document.getElementById('light').style.display='block';
document.getElementById('fade').style.display='block';
}
function lightboxhide(){
document.getElementById('light').style.display='none';
document.getElementById('fade').style.display='none';
}
function loadfiles(){
$.ajax({
url:'$url',
type:'POST',
dataType:'json',
success:function(data){
var result=eval(data);
$.each(result,function(key,value){
if(key=='FILELIST'){
filelistfunction(value);
}else if(key=='DIRLIST'){
directorylistfunction(value);
}
});
lightboxhide();
}
});
lightboxloader();
}
function directorylistfunction(value){
var dirnamestring='<table><tr><th>Directory List</th></tr>';
$.each(value,function(key,value){
var dirname=value['name'];
var dir_rootname=value['dirname'];
dirnamestring+='<tr><td><a href=\"#\" id=\"'+dir_rootname+'\">'+dirname+'</a></td></tr>';
});
dirnamestring+='</table>';
$('#directorydiv').html(dirnamestring);
}
function filelistfunction(value){
var filestring='<table><tr><th>File List</th></tr>';
$.each(value,function(key,value){
var filename=value['name'];
var filedirname=value['dirname'];
filestring+='<tr><td><input type=\"checkbox\" name=\"filenames[]\" class=\"filenames\"><a href=\"#\" id=\"'+filedirname+'/'+filename+'\" class=\"tooltip\">'+filename+'</a></input></td></tr>';
});
filestring+='<tr><td><input type=\"button\" value=\"Move\" id=\"filemovebtn\" />';
filestring+='</table>';
$('#filesdiv').html(filestring);
}
");
?>
<div class="fileftp">
<h1>FILE LIST From FTP</h1>
<input type="button" value="Load" id="loadbtn" />
<div id="fileftpdiv">
<div id="directorydiv"></div>
<div id="filesdiv"></div>
</div></div>
</div>
<div id="light" class="white_content"><img src="<?php echo Yii::app()->baseUrl."/images/ajax-loader.gif"; ?>" /></div>
<div id="fade" class="black_overlay"></div>
<style type="text/css">
#loadbtn {margin-left: 50px;}
#fileftpdiv{width:100%;}
#fileftpdiv #directorydiv{width:30%;float: left;}
#fileftpdiv #filesdiv{width:60%;float: left;}
#fileftpdiv table{width:100%;}
#fileftpdiv a{text-decoration: none;}
.fileftp #fileftpdiv{width: 100%;}
.fileftp table td{padding: 5px 6px;border-bottom: 1px solid #EEE;}
.fileftp table th{padding: 5px 6px;border-top: 1px solid white;border-bottom: 1px solid #EEE;}
.black_overlay{display: none;position: absolute;top: 0%;left: 0%;width: 100%;height: 100%;background-color: white;z-index:1001;-moz-opacity: 0.8;opacity:.80;filter: alpha(opacity=80);}
.white_content {display: none;position: absolute;z-index:1002;overflow: auto;}
/*.a:hover {background:#ffffff; text-decoration:none;} */ /*BG color is a must for IE6*/
/*a.tooltip span {display:none; padding:2px 3px; margin-left:8px; width:130px;}
a.tooltip:hover span{display:inline; position:absolute; background:#ffffff; border:1px solid #cccccc; color:#6c6c6c;}*/
</style>