<?php
/**
 * Created by PhpStorm.
 * User: 中闽 < 1464674022@qq.com >
 * Date: 2020/7/23
 * Time: 17:56
 */

namespace network;

use file\PathHelper;
use think\Exception;

class FtpHelper
{
    private $f_conn;

    /**
     * @param $host
     * @param $user
     * @param $pwd
     * @param int $port
     * @return resource
     * @throws Exception
     */
    public function connect($host, $user, $pwd, $port = 21)
    {
        if (!empty($this->f_conn)) {
            return $this->f_conn;
        }
        // 连接ftp
        $f_conn = ftp_connect($host, $port);
        if (!$f_conn) {
            throw new Exception("ftp connect fail");
        }
        // 登录ftp
        $f_login = ftp_login($f_conn, $user, $pwd);
        if (!$f_login) {
            throw new Exception("ftp login fail");
        }
        ftp_set_option($f_conn, FTP_USEPASVADDRESS, false); //考虑到不同ftp环境，需要加此参数，否则可能会出现连接超时错误
        ftp_pasv($f_conn, TRUE);//被动模式打开
        $this->f_conn = $f_conn;
        return $f_conn;
    }

    /**
     * 获取当前所在的ftp目录
     * @return string
     * @throws Exception
     */
    public function pwd()
    {
        $in_dir = ftp_pwd($this->f_conn);
        if (!$in_dir) {
            throw new Exception("ftp pwd fail");
        }
        return $in_dir;
    }

    /**
     * 获取当前所在ftp目录下包含的目录与文件的路径列表
     * @param null $path
     * @return array
     */
    public function ls($path = null)
    {
        if (empty($path)) {
            $path = ftp_pwd($this->f_conn);
        }
        //有时候末尾没有/会直接返回false,但是加上会读取不出文件夹
        return ftp_nlist($this->f_conn, $path);
    }

    /**
     * 详细列表
     * drw-rw-rw- 1 ftp ftp 0 Feb 07 16:01 course
     * @param null $path
     * @return array
     */
    public function ll($path = null)
    {
        if (empty($path)) {
            $path = ftp_pwd($this->f_conn);
        }
        //有时候末尾没有/会读取不出文件夹
        return ftp_rawlist($this->f_conn, appendEndDS($path, '/'));
    }

    /**
     * 如不存在则进行创建，多级目录需要一层一层创建
     * @param $dir_name string 相对根目录的路径
     * @return bool
     */
    public function mkdir($dir_name)
    {
        if (empty($dir_name)) {
            return false;
        }
        $dir_name = replaceUrlDS($dir_name);
        $dir_name = deleteStartDS($dir_name, '/');
        $root_dir = $this->pwd();
        //要新建的远程目录
        $new_dir = ($root_dir == '/') ? ("/" . $dir_name) : ("$root_dir/$dir_name");
        //远程父目录下列表
        $new_dir_parent = PathHelper::getParentDir($new_dir, '/');
        $exist_dirs = $this->ls($new_dir_parent);
        //检查目录下是否已存在同名文件夹
        if (!$exist_dirs || !in_array($new_dir, $exist_dirs)) {
            return @ftp_mkdir($this->f_conn, $dir_name);
        }
        return false;
    }

    /**
     * 切换目录
     * @param $dir_name
     * @return bool
     */
    public function cd($dir_name)
    {
        return ftp_chdir($this->f_conn, $dir_name);
    }

    /**
     * 进行文件上传,会覆盖同名文件
     * @param $remote_file [上传后的文件名.带扩展名]
     * @param $local_file [文件物理路径]
     * @return bool
     */
    public function upload($remote_file, $local_file)
    {
        $remote_file = replaceUrlDS($remote_file);
        $remote_file = deleteStartDS($remote_file, '/');
        return ftp_put($this->f_conn, $remote_file, $local_file, FTP_BINARY);
    }

    /**
     * 进行ftp下载
     * @param $local_file [本地保存路径]
     * @param $remote_file [ftp的相对路径，相对于$ftp->pwd()的路径]
     * @return bool
     */
    public function download($local_file, $remote_file)
    {
        return ftp_get($this->f_conn, $local_file, $remote_file, FTP_BINARY);
    }

    /**
     * @param $remote_file
     * @return bool
     */
    public function delete($remote_file)
    {
        return ftp_delete($this->f_conn, $remote_file);
    }

    //测试
    public function test()
    {
//        $root_path = \app\common\model\FileManageModel::getRootDir();
//        $ftp = new FtpHelper();
//        $ftp->connect('ftp.test.com', 'test', '123123');

//        var_dump($ftp->pwd());//显示当前路径
//        $ftp->upload('test.html', $root_path . DS . 'test.html');//上传
//        var_export($ftp->ls());//显示文件列表
//        $ftp->download('./test.html', '/test_dir/test2.html');//下载
//
//        $ftp->mkdir('test_dir/test_dir2');//新建多级目录，上级目录必须存在，文件分隔符linux上不可使用\,windows没测试过
//        $ftp->cd('test_dir');//切换目录
//        $ftp->mkdir('test_dir3');//新建目录/test/test_dir3
//        $ftp->mkdir('/test_dir4');//新建目录/test_dir4

//        var_dump($ftp->pwd());//显示当前路径
//        $ftp->upload('test2.html', $root_path . DS . 'test2.html');//上传
//        var_export($ftp->ls());//显示文件列表
//        $ftp->download($root_path . DS . 'down_test2.html', $ftp->pwd() . '/test2.html');//这里$remote_file等同于'./test2.html'


        //测试指定路径上传
//        $ftp->upload('/mkdir.html', $root_path . DS . 'test.html');
//        $ftp->upload('/test_dir/mkdir.html', $root_path . DS . 'test.html');
//        $ftp->upload('/test_dir2/mkdir.html', $root_path . DS . 'test.html');//如果test_dir2不存在，会报错

    }
}