FTP Download with the CodeIgniter FTP Library

I was recently working on a project that involved FTP and I thought it would be a great chance to get away from the built-in PHP functionality and use the CodeIgniter FTP library instead.

I was pretty surprised to find that there was no download functionality in the base FTP library as of CI 1.7.2. I’ve extended the library to incorporate file download and will share that here.

<?php

// This codes goes in the 'application/libraries' folder with a
// file name of MY_Ftp.php

class MY_Ftp extends CI_Ftp {

	/**
	 * Constructor
	 **/
	function MY_Ftp() {
		parent::CI_Ftp();
	}
	
	/**
	 * Download a file from a FTP server
	 * @param	<string>	$rem_path	Remote path of the file to download
	 * @param	<string>	$loc_path	Local path destination for download
	 * @param	<string>	$mode		Transfer mode, defaults to auto
	 **/
	function download($rem_path, $loc_path, $mode='auto') {
		// check for an active connection
		if ( ! $this->_is_conn()) {
			return FALSE;
		}
	
		// get remote folder/filename
		$rem_folder   = dirname($rem_path);
		$rem_filename = basename($rem_path);
	
		// if a local directory was passed handle differently.
		// Otherwise, treat same as remote.
		if (@is_dir($loc_path)) {
			$loc_folder   = rtrim($loc_path, '/');
			$loc_filename = $rem_filename;
		}
		else {
			$loc_folder   = dirname($loc_path);
			$loc_filename = basename($loc_path);
		}
	
		// check that the loc path exists
		if ( $loc_folder != '.'  && ! @is_dir($loc_folder)) {
			$this->_error('ftp_bad_loc_path');
			return FALSE;
		}
		// check that loc path and file are writable
		elseif ( ! @is_writable($loc_folder) OR (file_exists($loc_folder.'/'.$loc_filename) && ! @is_writable($loc_folder.'/'.$loc_filename))) {
			$this->_error('ftp_loc_not_write');
			return FALSE;
		}
	
		// store old paths
		$old_rem_path = @ftp_pwd($this->conn_id);
		$old_loc_path = getcwd();
	
		// move to the local path
		if ( ! @chdir($loc_folder)) {
			$this->_error('ftp_bad_loc_path');
			return FALSE;
		}
	
		// move to the remote path
		if ( $rem_folder != '.' && ! $this->changedir($rem_folder)) {
			$this->_error('ftp_bad_rem_path');
			return FALSE;
		}
	
		// check that the file exists remotely
		$found_file = FALSE;
		$files = $this->list_files();
		if (count($files) > 0) {
			foreach ($files as $f) {
				if ($f == $rem_filename) {
					$found_file = TRUE;
					break;
				}
			}
		}
	
		if ( ! $found_file) {
			$this->_error('ftp_bad_rem_file');
			@chdir($old_loc_path);
			return FALSE;
		}
	
		// Set the mode if not specified
		if ($mode == 'auto') {
			// Get the file extension so we can set the upload type
			$ext = $this->_getext($rem_path);
			$mode = $this->_settype($ext);
		}
	
		$mode = ($mode == 'ascii') ? FTP_ASCII : FTP_BINARY;
	
		// download the file
		$result = @ftp_get($this->conn_id, $loc_folder.'/'.$loc_filename, $rem_filename, $mode);
	
		if ($result === FALSE) {
			if ($this->debug == TRUE)
				$this->_error('ftp_unable_to_download');
	
			return FALSE;
		}
	
		// move back to the root path
		$this->changedir($old_rem_path);
		@chdir($old_loc_path);
	
		return TRUE;
	}

}

As a side note, you will need to tweak your language file to include all of the message codes (e.g., ftp_bad_loc_path) passed to _error() for proper error display in your app.

Want more articles like this one in your Inbox? Subscribe