* 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不存在,会报错 } }