首页 > 代码库 > 让thinkphp 支持ftp上传到远程,ftp删除

让thinkphp 支持ftp上传到远程,ftp删除

让thinkphp真正的支持FTP上传,删除。原创by default7#zbphp.com,如需转载请保留作者信息。 /**
 * This is not a free software, All Copyright @F.Z.B
 * Date: 2014/10/21 10:51
 * File: MyFtpUpload.php
 * Author: default7 <default7@zbphp.com>
 */
include ‘Ftp.php‘;

class MyFtpUpload
{
    //必须支持swf jpg jpeg png gif bmp txt log
    public $allowType = ‘swf|png|jpg|gif|jpeg‘;
    public $locFolder = ‘uploads‘;

    static $ftpHandler = null;
    static $config = null;

    public function __construct()
    {
        if (self::$config === null) {
            self::$config = C(‘MY_CI_FTP_CONFIG‘);
        }
    }

    public function __destruct()
    {
        if (self::$ftpHandler !== null) {
            self::$ftpHandler->close();
        }
    }

    /**
     * @description 单例模式
     * @return null
     */
    public function getInstance()
    {
        if (self::$ftpHandler === null) {
            $ftp = new CI_FTP(self::$config);
            $ftp->connect();
            self::$ftpHandler = $ftp;
        }

        return self::$ftpHandler;
    }


    /**
     * @description 检测文件大小是否溢出
     *
     * @param $size
     *
     * @return bool
     */
    function isSizeOver($size)
    {
        return !empty(self::$config[‘maxsize‘]) && $size > self::$config[‘maxsize‘] ? true : false;
    }

    /**
     * @description 一行上传 支持单个
     *
     * @param        $file
     * @param string $saveFolder
     * @param string $allowType
     *
     * @return array
     */
    public function autoUpload($file, $saveFolder = ‘‘, $allowType = ‘‘)
    {
        if (empty($allowType)) $allowType = $this->allowType;
        $ext = $this->getExt($file[‘name‘]);
        if (!$this->isAllowExt($ext, $allowType)) {
            return array(false, 不允许的格式. $ext);

        }
        $savePath = $this->mkSavePath($saveFolder, $ext);
        if (!$this->ftpUpload($file[‘tmp_name‘], $savePath)) {
            return array(false, 文件上传失败,请联系管理员或重试!);
        }

        return array(true, $savePath);
    }

    /**
     * @description 输入本地的存放地址路径,输入远程的存放路径
     *
     * @param $localPath
     * @param $savePath
     *
     * @return mixed
     */
    function ftpUpload($localPath, $savePath)
    {
        if (!self::$config) return false;
        $dir = trim(dirname($savePath));
        if (!self::getInstance()->changedir($dir)) {
            self::getInstance()->mkdir($dir);
            self::getInstance()->chmod($dir, 0777);
        }

        $result = self::getInstance()->upload($localPath, $savePath);

        return $result;
    }


    //先保存到本地 再上传到远程
    public function saveTxtFile($savePath, $content, $locFolder = ‘uploads‘)
    {
        $locPath = $locFolder . $savePath;
        $arr = explode(‘/‘, dirname($locPath));
        $dir = ‘.‘;
        foreach ($arr as $d) {
            $comma = ‘/‘;
            $dir .= $comma . $d;
            if (!is_dir($dir) && !mkdir($dir)) return false;
        }

        //保存文件失败
        if (empty($content)) $content = ‘ ‘;//防止 file_put_content 保存失败
        if (!file_put_contents($locPath, $content)) {
            return false;
        }

        return $this->ftpUpload($locPath, $savePath);
    }

    //读取远程文件 先读取本地,否则读取远程
    public function readTxtFile($filePath, $locFolder = ‘uploads‘)
    {
        $content = ‘‘;
        $locPath = ‘./‘ . $locFolder . $filePath;
        if (!(file_exists($locPath) && is_file($locPath))) {
            self::getInstance()->download($filePath, $locPath);
        }
        if (is_file($locPath)) $content = file_get_contents($locPath);

        return $content;
    }

    /**
     * @description 删除本地 同时删除远程
     *
     * @param        $path
     * @param string $locFolder
     * @param string $allowType
     *
     * @return bool
     */
    public function delTxtFile($path, $locFolder = ‘uploads‘, $allowType = ‘‘)
    {
        if (!empty($path)) {
            if (empty($allowType)) $allowType = $this->allowType;
            $ext = $this->getExt($path);
            if ($this->isAllowExt($ext, $allowType)) {
                $locPath = ‘./‘ . $locFolder . $path;
                if (file_exists($locPath)) {
                    @unlink($locPath);
                }

                return $this->ftpDelFile($path, $allowType);
            }
        }

        return array(false, 文件. $path . 删除失败,请联系管理员!);
    }

    /**
     * @description 文件名中含有 至少2个数字表示非默认文件
     *
     * @param $filepath
     *
     * @return bool
     */
    public function isDefaultFile($filepath)
    {
        return preg_match(‘/\d{2,}/‘, basename($filepath)) ? false : true;
    }

    /**
     * @description 默认图片/文件是不允许删除!
     *
     * @param        $filePath
     * @param string $allowType
     *
     * @return array
     */
    public function ftpDelFile($filePath, $allowType = ‘‘)
    {
        if (!self::$config) return array(false, 未配置FTP登录信息);

        //是否是默认图片
        if ($this->isDefaultFile($filePath)) {
            return array(false, 默认图片不允许删除!);
        }

        if (strpos($filePath, ‘..‘) !== false) {
            return array(false, 文件或目录地址中不能包含 .. );
        }

        if (empty($allowType)) $allowType = $this->allowType;
        $ext = $this->getExt($filePath);
        if (!$this->isAllowExt($ext, $allowType)) {
            return array(false, 不允许的删除格式!);
        }

        $result = self::getInstance()->delete_file($filePath);

        return array($result, ‘‘);
    }

    /**
     * @param $filename
     *
     * @return string
     */
    function getExt($filename)
    {
        if (false === strpos($filename, ‘.‘)) {
            return ‘‘;
        }

        $x = explode(‘.‘, $filename);

        return ‘.‘ . strtolower(end($x));
    }

    /**
     * @description 输入的扩展名必须以.开头
     *
     * @param        $ext
     * @param string $allowType
     *
     * @return bool
     */
    function isAllowExt($ext, $allowType = ‘‘)
    {
        if ($allowType == ‘*‘) return true;
        if (empty($allowType)) $allowType = $this->allowType;

        return $ext && preg_match(‘/^\.(‘ . $allowType . ‘)$/i‘, $ext) ? true : false;
    }

    /**
     * @description 生成上传地址 完整上传地址
     *              开头必须是 斜杠,包含完整扩展名
     *
     * @param string $folder
     * @param string $ext
     *
     * @return mixed
     */
    public function mkSavePath($folder = ‘‘, $ext = ‘‘)
    {
        $savePath = ‘/‘ . $folder . ‘/‘ . date(‘ym‘) . ‘/‘ . date(‘ymdHis_‘) . rand(10, 99) . $ext;

        return str_replace(‘//‘, ‘/‘, $savePath);
    }

    /**
     * @description 检测是否是图片文件
     *
     * @param        $filepath
     * @param string $ext
     *
     * @return bool
     */
    public function isImageFile($filepath, $ext = ‘‘)
    {
        $imginfo = getimagesize($filepath);
        if (empty($imginfo) || ($ext == ‘gif‘ && empty($imginfo[‘bits‘]))) {
            return false;
        }

        return true;
    }

    /**
     * @description 通过保存路径获取网址
     *
     * @param $savePath
     *
     * @return string
     */
    public function getUrl($savePath)
    {
        $url = ‘‘;
        if (preg_match(‘/^https?:/‘, $savePath)) {
            $url = $savePath;

        } else if (!empty($savePath)) {
            $url .= self::$config[‘siteurl‘];
            $url .= $savePath;
        }

        return $url;
    }
}

// ------------------------------------------------------------------------
/**
 * FTP Class
 *
 * @package       CodeIgniter
 * @subpackage Libraries
 * @category   Libraries
 * @author    ExpressionEngine Dev Team
 * @link      http://codeigniter.com/user_guide/libraries/ftp.html
 */
class CI_FTP {

   var $hostname  = ‘‘;
   var $username  = ‘‘;
   var $password  = ‘‘;
   var $port     = 21;
   var $passive   = TRUE;
   var $debug    = FALSE;
   var $conn_id   = FALSE;


   /**
    * Constructor - Sets Preferences
    *
    * The constructor can be passed an array of config values
    */
   public function __construct($config = array())
   {
      if (count($config) > 0)
      {
         $this->initialize($config);
      }

   }

   // --------------------------------------------------------------------

   /**
    * Initialize preferences
    *
    * @access public
    * @param  array
    * @return void
    */
   function initialize($config = array())
   {
      foreach ($config as $key => $val)
      {
         if (isset($this->$key))
         {
            $this->$key = $val;
         }
      }

      // Prep the hostname
      $this->hostname = preg_replace(‘|.+?://|‘, ‘‘, $this->hostname);
   }

   // --------------------------------------------------------------------

   /**
    * FTP Connect
    *
    * @access public
    * @param  array   the connection values
    * @return bool
    */
   function connect($config = array())
   {
      if (count($config) > 0)
      {
         $this->initialize($config);
      }

      if (FALSE === ($this->conn_id = @ftp_connect($this->hostname, $this->port)))
      {
         if ($this->debug == TRUE)
         {
            $this->_error(‘ftp_unable_to_connect‘);
         }
         return FALSE;
      }

      if ( ! $this->_login())
      {
         if ($this->debug == TRUE)
         {
            $this->_error(‘ftp_unable_to_login‘);
         }
         return FALSE;
      }

      // Set passive mode if needed
      if ($this->passive == TRUE)
      {
         ftp_pasv($this->conn_id, TRUE);
      }

      return TRUE;
   }

   // --------------------------------------------------------------------

   /**
    * FTP Login
    *
    * @access private
    * @return bool
    */
   function _login()
   {
      return @ftp_login($this->conn_id, $this->username, $this->password);
   }

   // --------------------------------------------------------------------

   /**
    * Validates the connection ID
    *
    * @access private
    * @return bool
    */
   function _is_conn()
   {
      if ( ! is_resource($this->conn_id))
      {
         if ($this->debug == TRUE)
         {
            $this->_error(‘ftp_no_connection‘);
         }
         return FALSE;
      }
      return TRUE;
   }

   // --------------------------------------------------------------------


   /**
    * Change directory
    *
    * The second parameter lets us momentarily turn off debugging so that
    * this function can be used to test for the existence of a folder
    * without throwing an error.  There‘s no FTP equivalent to is_dir()
    * so we do it by trying to change to a particular directory.
    * Internally, this parameter is only used by the "mirror" function below.
    *
    * @access public
    * @param  string
    * @param  bool
    * @return bool
    */
   function changedir($path = ‘‘, $supress_debug = FALSE)
   {
      if ($path == ‘‘ OR ! $this->_is_conn())
      {
         return FALSE;
      }

      $result = @ftp_chdir($this->conn_id, $path);

      if ($result === FALSE)
      {
         if ($this->debug == TRUE AND $supress_debug == FALSE)
         {
            $this->_error(‘ftp_unable_to_changedir‘);
         }
         return FALSE;
      }

      return TRUE;
   }

   // --------------------------------------------------------------------

   /**
    * Create a directory
    *
    * @access public
    * @param  string
    * @return bool
    */
   function mkdir($path = ‘‘, $permissions = NULL)
   {
      if ($path == ‘‘ OR ! $this->_is_conn())
      {
         return FALSE;
      }

      $result = @ftp_mkdir($this->conn_id, $path);

      if ($result === FALSE)
      {
         if ($this->debug == TRUE)
         {
            $this->_error(‘ftp_unable_to_makdir‘);
         }
         return FALSE;
      }

      // Set file permissions if needed
      if ( ! is_null($permissions))
      {
         $this->chmod($path, (int)$permissions);
      }

      return TRUE;
   }

   // --------------------------------------------------------------------

   /**
    * Upload a file to the server
    *
    * @access public
    * @param  string
    * @param  string
    * @param  string
    * @return bool
    */
   function upload($locpath, $rempath, $mode = ‘auto‘, $permissions = NULL)
   {
      if ( ! $this->_is_conn())
      {
         return FALSE;
      }

      if ( ! file_exists($locpath))
      {
         $this->_error(‘ftp_no_source_file‘);
         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($locpath);
         $mode = $this->_settype($ext);
      }

      $mode = ($mode == ‘ascii‘) ? FTP_ASCII : FTP_BINARY;

      $result = @ftp_put($this->conn_id, $rempath, $locpath, $mode);

      if ($result === FALSE)
      {
         if ($this->debug == TRUE)
         {
            $this->_error(‘ftp_unable_to_upload‘);
         }
         return FALSE;
      }

      // Set file permissions if needed
      if ( ! is_null($permissions))
      {
         $this->chmod($rempath, (int)$permissions);
      }

      return TRUE;
   }

   // --------------------------------------------------------------------

   /**
    * Download a file from a remote server to the local server
    *
    * @access public
    * @param  string
    * @param  string
    * @param  string
    * @return bool
    */
   function download($rempath, $locpath, $mode = ‘auto‘)
   {
      if ( ! $this->_is_conn())
      {
         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($rempath);
         $mode = $this->_settype($ext);
      }

      $mode = ($mode == ‘ascii‘) ? FTP_ASCII : FTP_BINARY;

      $result = @ftp_get($this->conn_id, $locpath, $rempath, $mode);

      if ($result === FALSE)
      {
         if ($this->debug == TRUE)
         {
            $this->_error(‘ftp_unable_to_download‘);
         }
         return FALSE;
      }

      return TRUE;
   }

   // --------------------------------------------------------------------

   /**
    * Rename (or move) a file
    *
    * @access public
    * @param  string
    * @param  string
    * @param  bool
    * @return bool
    */
   function rename($old_file, $new_file, $move = FALSE)
   {
      if ( ! $this->_is_conn())
      {
         return FALSE;
      }

      $result = @ftp_rename($this->conn_id, $old_file, $new_file);

      if ($result === FALSE)
      {
         if ($this->debug == TRUE)
         {
            $msg = ($move == FALSE) ? ‘ftp_unable_to_rename‘ : ‘ftp_unable_to_move‘;

            $this->_error($msg);
         }
         return FALSE;
      }

      return TRUE;
   }

   // --------------------------------------------------------------------

   /**
    * Move a file
    *
    * @access public
    * @param  string
    * @param  string
    * @return bool
    */
   function move($old_file, $new_file)
   {
      return $this->rename($old_file, $new_file, TRUE);
   }

   // --------------------------------------------------------------------

   /**
    * Rename (or move) a file
    *
    * @access public
    * @param  string
    * @return bool
    */
   function delete_file($filepath)
   {
      if ( ! $this->_is_conn())
      {
         return FALSE;
      }

      $result = @ftp_delete($this->conn_id, $filepath);

      if ($result === FALSE)
      {
         if ($this->debug == TRUE)
         {
            $this->_error(‘ftp_unable_to_delete‘);
         }
         return FALSE;
      }

      return TRUE;
   }

   // --------------------------------------------------------------------

   /**
    * Delete a folder and recursively delete everything (including sub-folders)
    * containted within it.
    *
    * @access public
    * @param  string
    * @return bool
    */
   function delete_dir($filepath)
   {
      if ( ! $this->_is_conn())
      {
         return FALSE;
      }

      // Add a trailing slash to the file path if needed
      $filepath = preg_replace("/(.+?)\/*$/", "\\1/",  $filepath);

      $list = $this->list_files($filepath);

      if ($list !== FALSE AND count($list) > 0)
      {
         foreach ($list as $item)
         {
            // If we can‘t delete the item it‘s probaly a folder so
            // we‘ll recursively call delete_dir()
            if ( ! @ftp_delete($this->conn_id, $item))
            {
               $this->delete_dir($item);
            }
         }
      }

      $result = @ftp_rmdir($this->conn_id, $filepath);

      if ($result === FALSE)
      {
         if ($this->debug == TRUE)
         {
            $this->_error(‘ftp_unable_to_delete‘);
         }
         return FALSE;
      }

      return TRUE;
   }

   // --------------------------------------------------------------------

   /**
    * Set file permissions
    *
    * @access public
    * @param  string the file path
    * @param  string the permissions
    * @return bool
    */
   function chmod($path, $perm)
   {
      if ( ! $this->_is_conn())
      {
         return FALSE;
      }

      // Permissions can only be set when running PHP 5
      if ( ! function_exists(‘ftp_chmod‘))
      {
         if ($this->debug == TRUE)
         {
            $this->_error(‘ftp_unable_to_chmod‘);
         }
         return FALSE;
      }

      $result = @ftp_chmod($this->conn_id, $perm, $path);

      if ($result === FALSE)
      {
         if ($this->debug == TRUE)
         {
            $this->_error(‘ftp_unable_to_chmod‘);
         }
         return FALSE;
      }

      return TRUE;
   }

   // --------------------------------------------------------------------

   /**
    * FTP List files in the specified directory
    *
    * @access public
    * @return array
    */
   function list_files($path = ‘.‘)
   {
      if ( ! $this->_is_conn())
      {
         return FALSE;
      }

      return ftp_nlist($this->conn_id, $path);
   }

   // ------------------------------------------------------------------------

   /**
    * Read a directory and recreate it remotely
    *
    * This function recursively reads a folder and everything it contains (including
    * sub-folders) and creates a mirror via FTP based on it.  Whatever the directory structure
    * of the original file path will be recreated on the server.
    *
    * @access public
    * @param  string path to source with trailing slash
    * @param  string path to destination - include the base folder with trailing slash
    * @return bool
    */
   function mirror($locpath, $rempath)
   {
      if ( ! $this->_is_conn())
      {
         return FALSE;
      }

      // Open the local file path
      if ($fp = @opendir($locpath))
      {
         // Attempt to open the remote file path.
         if ( ! $this->changedir($rempath, TRUE))
         {
            // If it doesn‘t exist we‘ll attempt to create the direcotory
            if ( ! $this->mkdir($rempath) OR ! $this->changedir($rempath))
            {
               return FALSE;
            }
         }

         // Recursively read the local directory
         while (FALSE !== ($file = readdir($fp)))
         {
            if (@is_dir($locpath.$file) && substr($file, 0, 1) != ‘.‘)
            {
               $this->mirror($locpath.$file."/", $rempath.$file."/");
            }
            elseif (substr($file, 0, 1) != ".")
            {
               // Get the file extension so we can se the upload type
               $ext = $this->_getext($file);
               $mode = $this->_settype($ext);

               $this->upload($locpath.$file, $rempath.$file, $mode);
            }
         }
         return TRUE;
      }

      return FALSE;
   }


   // --------------------------------------------------------------------

   /**
    * Extract the file extension
    *
    * @access private
    * @param  string
    * @return string
    */
   function _getext($filename)
   {
      if (FALSE === strpos($filename, ‘.‘))
      {
         return ‘txt‘;
      }

      $x = explode(‘.‘, $filename);
      return end($x);
   }


   // --------------------------------------------------------------------

   /**
    * Set the upload type
    *
    * @access private
    * @param  string
    * @return string
    */
   function _settype($ext)
   {
      $text_types = array(
                     ‘txt‘,
                     ‘text‘,
                     ‘php‘,
                     ‘phps‘,
                     ‘php4‘,
                     ‘js‘,
                     ‘css‘,
                     ‘htm‘,
                     ‘html‘,
                     ‘phtml‘,
                     ‘shtml‘,
                     ‘log‘,
                     ‘xml‘
                     );


      return (in_array($ext, $text_types)) ? ‘ascii‘ : ‘binary‘;
   }

   // ------------------------------------------------------------------------

   /**
    * Close the connection
    *
    * @access public
    * @param  string path to source
    * @param  string path to destination
    * @return bool
    */
   function close()
   {
      if ( ! $this->_is_conn())
      {
         return FALSE;
      }

      @ftp_close($this->conn_id);
   }

   // ------------------------------------------------------------------------

   /**
    * Display error message
    *
    * @access private
    * @param  string
    * @return bool
    */
   function _error($line)
   {
        exit($line);
//    $CI =& get_instance();
//    $CI->lang->load(‘ftp‘);
//    show_error($CI->lang->line($line));
   }


}
// END FTP Class

/* End of file Ftp.php */
/* Location: ./system/libraries/Ftp.php */

#配置config.php#

//本地测试环境
    ‘MY_CI_FTP_CONFIG‘       => array(
        ‘hostname‘ => ‘127.0.0.1‘,
        ‘username‘ => ‘php‘,
        ‘password‘ => ‘123456‘,
        ‘debug‘    => false,
        ‘passive‘  => false,
        ‘maxsize‘  => 1048576,//最大上传1M
        ‘siteurl‘  => ‘http://localhost‘,//结尾不要有反斜杠
    ),


#使用方法#
$file = $_FILES[‘upfile‘];
import(‘Common.Vendor.CodeIgniter.MyFtpUpload‘, ‘‘, ‘.php‘);
$myFtp = new \MyFtpUpload();
if (is_uploaded_file($file[‘tmp_name‘])) {

    if ($myFtp->isSizeOver(filesize($file[‘tmp_name‘]))) {
        $this->error("上传文件不能超过1MB");
    }

    $ext = $myFtp->getExt($file[‘name‘]);
    if (!($myFtp->isAllowExt($ext, ‘jpg|gif|png|jpeg‘) && $myFtp->isImageFile($file[‘tmp_name‘], $ext))) {
        $this->error("不支持的文件格式!上传的头像必须是图片!");
    }
    $savePath = ‘/avatar/‘ . $UserId . $ext;
    if (!$myFtp->ftpUpload($file[‘tmp_name‘], $savePath)) {
        $this->error("头像上传失败!");
    }
    $newHeadphoto = $data[‘avatar‘] = $savePath;
}

让thinkphp 支持ftp上传到远程,ftp删除