php单文件管理器:
前言:
项目开发过程中,网站一般部署到远程服务器,所以文件管理就不能和本机操作一样方便。通常文件管理是用ftp下载到本地,修改后再上传,或者远程登录到服务器进行修改。但是这些操作都依赖于复杂的第三方软件。如果只是想简单修改网站中一个页面中的文字,或查看文件代码,相对于繁琐的使用第三方软件进行操作的流程,如果有一个小程序能在线操作文件,那就能方便快速达到自己的需求了。所以,SuExplorer就是在这样的需求中被开发出来。
秉承自己开发的小工具一贯的风格,首先是要尽可能绿色单文件,尽量不依赖其他文件,然后是容易部署。 这样才能方便在项目中提高生产力!
简介:
SuExplorer_PHP是一个用于在线管理文件的单文件绿色版PHP程序,和phpinfo.php一样可以方便放到项目中使用。 开发项目过程中,操作服务器上的文件是一个费时费力的流程,如果有一个通用管理程序,可以很简单而高效地管理服务器上的文件,那对项目的开发效率肯定有明显的提升,可以减少很多重复而单调的体力劳动。但是,管理服务器上的文件,首先要连接上服务器,然后用第三方工具进行操作,为了简单查看一下文件源码,却要安装一大堆不需要的依赖文件,而且还要开启和关闭第三方软件,效率有点低。于是决定自己抽出一点时间来开发一个自己用起来顺手的在线文件管理小工具,简单而高效,用起来还顺手~
特性:
1、单文件绿色版,无外部依赖,方便部署使用 2、支持登录验证 3、支持内置配置文件,使用更灵活 功能:
- 在线创建文件或目录
- 在线删除文件或目录
- 在线重命名文件或目录
- 在线编辑文本文件
- 在线上传文件
- 在线压缩
- 在线解压缩
使用: - SuExplorer_3_1文件复制到您的项目中任意目录(本文件为单文件绿色版,方便使用).
- 修改配置内容为适合您需要的规则.
- 运行本文件, 开始在线管理文件
项目地址:https://gitee.com/sutroon/SuExplorer_PHP_3_0
php单文件管理器:
<?php session_start(); /** * SuExplorer.php * 在线php/ini/conf/sh等脚本文件编辑器, 不依赖ftp和服务器帐号(单页绿色文件,方便部署) * @since 1.0 <2015-5-11> SoChishun <14507247@qq.com> Added. * @since 2.0 <2015-7-24> SoChishun * 1.重命名为SuExplorer.php * 2.改进若干外观样式 * 3.新增登录验证模块 * 4.新增删除功能 * @since 3.0 <2015-10-7> SoChishun * 1.新增在线压缩和解压功能 * 2.新增chomd权限设置功能 * 3.新增rename重命名功能 * 4.新增新建文件和目录功能 * 5.类SuFileEditor重构为SuExplorer,类方法改为静态方法 * 6.新增主配置文件功能 * 7.重构页面逻辑,改为脚本混合代码,便于阅读 * 8.基于绝对路径操作改为基于网站根目录的相对路径操作 * @since 3.1 <2016-9-13> SoChishun * 1. 新增文件上传功能 * @since 3.2 <2017-8-23> SoChishun * 1. 修正无法查看脚本文件的问题 * 2. 对html输出增加htmlspecialchars过滤功能 */ // 程序版本号 [2015-10-7] Added. $version = '3.2'; // session键名 [2015-10-7] Added. $sess_id = 'sess_suexplorer'; // 权限规则 [2015-10-7] Added. $prules = array('delfile', 'deldir', 'savefile', 'newfile', 'mkdir', 'renamefile', 'renamedir', 'chomdfile', 'chomddir', 'zip', 'unzip'); // 主配置 [2015-10-7] Added. $config = array( /* 用户配置 */ 'users' => array( 'admin' => array('admin123', array('allow' => array(), 'forbit' => array())), 'test' => array('testpwd', array('allow' => array(), 'forbit' => array())), ), ); // 登录信息 [2015-10-7] Added. $login_data = isset($_SESSION[$sess_id]) ? $_SESSION[$sess_id] : false; $action = I('action'); $view = I('view'); $path = I('path', '/'); // urldecode($_GET['path']) $_SERVER['DOCUMENT_ROOT'] $parent_path = path_getdir($path); switch ($action) { case 'login': // 用户登录 if (!SuExplorer::user_login($config, $sess_id, $msg)) { redirect('?r=fail', 1, $msg); } else { redirect('?r=ok'); } break; case 'logout': // 注销登录 SuExplorer::user_logout($sess_id); redirect('?r=ok'); break; case 'del': // 删除路径(文件或目录) if (!SuExplorer::act_delete_path($path, $msg)) { redirect('?path=' . $path, 1, $msg); } else { redirect('?path=' . path_getdir($path), 1, '恭喜,操作成功!'); } break; case 'savefile': // 保存文件 case 'save_newfile': // 新建文件 if (!SuExplorer::act_save_file($msg)) { redirect('?path=' . $path, 1, $msg); } else { redirect('?path=' . $path, 1, '恭喜,操作成功!'); } break; case 'save_newdir': // 新建目录 if (!SuExplorer::act_save_newdir($msg)) { redirect('?path=' . $path, 1, $msg); } else { redirect('?path=' . $path, 1, '恭喜,操作成功!'); } break; case 'upload_file': // 上传文件 if (!SuExplorer::act_upload_file($msg)) { redirect('?path=' . $path, 1, $msg); } else { redirect('?path=' . $path, 1, '恭喜,文件上传成功!'); } break; case 'rename_path': // 重命名路径(文件或目录) if (!SuExplorer::act_rename_path($msg)) { redirect('?path=' . $path, 1, $msg); } else { redirect('?path=' . pathinfo($path, PATHINFO_DIRNAME), 1, '恭喜,操作成功!'); } break; case 'chmod_path': // 修改权限(文件或目录) if (!SuExplorer::act_chmod_path($msg)) { redirect('?path=' . $path, 1, $msg); } else { redirect('?path=' . $path, 1, '恭喜,操作成功!'); } break; case 'zip': // 压缩 if (!SuExplorer::act_zip($msg)) { redirect('?path=' . $path, 1, $msg); } else { redirect('?path=' . $path, 1, '恭喜,操作成功!'); } break; case 'unzip': // 解压缩 if (!SuExplorer::act_unzip($msg)) { redirect('?path=' . $path, 1, $msg); } else { redirect('?path=' . $path, 1, '恭喜,操作成功!'); } break; } ?> "UTF-8"><?php endif; ?> <?php /* * **************************************************************************************************** 函数 :) * **************************************************************************************************** */ /** * 获取浏览器参数 * @param string $name * @param mixed $defv * @return mixed * @since 1.0 <2015-8-13> SoChishun Added. */ function I($name, $defv = '') { if (isset($_GET[$name])) { return $_GET[$name]; } return isset($_POST[$name]) ? $_POST[$name] : $defv; } /** * URL重定向 * @param string $url 重定向的URL地址 * @param integer $time 重定向的等待时间(秒) * @param string $msg 重定向前的提示信息 * @return void * @since 1.0 <2015-10-7> from ThinkPHP */ function redirect($url, $time = 0, $msg = '') { //多行URL地址支持 $url = str_replace(array("\n", "\r"), '', $url); if (empty($msg)) $msg = "系统将在{$time}秒之后自动跳转到{$url}!"; if (!headers_sent()) { // redirect if (0 === $time) { header('Location: ' . $url); } else { header("refresh:{$time};url={$url}"); echo($msg); } exit(); } else { $str = ""; if ($time != 0) $str .= $msg; exit($str); } } /** * 获取文件扩展名类型 * @param string $exten 扩展名(不带.) * @return string * @since 1.0 <2015-10-9> SoChishun Added. */ function get_exten_catetory($exten) { if ($exten) { $filetypes = array('zip' => array('zip', 'rar', '7-zip', 'tar', 'gz', 'gzip'), 'doc' => array('txt', 'rtf', 'doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx', 'wps', 'et'), 'script' => array('php', 'js', 'css', 'c'), 'image' => array('jpg', 'jpeg', 'png', 'gif', 'tiff', 'psd', 'bmp', 'ico')); foreach ($filetypes as $catetory => $extens) { if (in_array($exten, $extens)) { return $catetory; } } } return ''; } /** * 绝对路径转相对路径 * @param string $path * @return string * @since 1.0 <2015-10-9> SoChishun Added. */ function path_ator($path) { $root = $_SERVER['DOCUMENT_ROOT']; $path = substr($path, strlen($root)); if ('/' != DIRECTORY_SEPARATOR) { $path = str_replace(DIRECTORY_SEPARATOR, '/', $path); } return $path; } /** * 相对路径转绝对路径 * @param string $path * @return string * @since 1.0 <2015-10-9> SoChishun Added. */ function path_rtoa($path) { $root = $_SERVER['DOCUMENT_ROOT']; if ('/' != DIRECTORY_SEPARATOR) { $path = str_replace('/', DIRECTORY_SEPARATOR, $path); } return $root . $path; } /** * 获取文件的目录地址 * @param string $path * @param boolean $is_r 是否相对路径 * @return string * @since 1.0 <2015-10-9> SoChishun Added. */ function path_getdir($path, $is_r = true) { if (!$path || is_dir($is_r ? path_rtoa($path) : $path)) { return $path; } return pathinfo($path, PATHINFO_DIRNAME); } /** * 页面主类 * @since 1.0 <2015-5-11> SoChishun <14507247@qq.com> Added. * @since 3.0 <2015-10-7> SoChishun 重构. */ class SuExplorer { /** * 版本号 * @var string * @since 1.0 <2015-10-7> SoChishun Added. */ CONST VERSION = '3.0.0'; /** * 显示网站目录的项目内容 * @since 1.0 <2015-5-11> SoChishun Added. */ static function index($view, $path) { // 面包屑导航 self::location_to_breadcrumb($path); // 视图显示 switch ($view) { case 'newfile': self::view_create_file($path); break; case 'newdir': self::view_create_dir($path); break; case 'upload': self::view_upload_file($path); break; case 'rename': self::view_rename_path($path); break; case 'chmod': self::view_chmod_path($path); break; case 'zip': self::view_zip(); break; case 'unzip': self::view_unzip(); break; default: // 列出文件 $sapath = path_rtoa($path); if (is_dir($sapath)) { self::view_content_list($path); } else if (is_file($sapath)) { self::view_edit_file($path); } else { echo '文件或目录不存在或已删除!'; } break; } } /** * 用户登录操作 * @param array $config * @param string $sess_id * @param string $msg 错误消息 * @return boolean * @since 1.0 <2015-10-9> SoChishun Added. */ static function user_login($config, $sess_id, &$msg = '') { if (!$_POST || !isset($_POST['uname'])) { $msg = '表单数据无效!'; return false; } $uname = $_POST['uname']; if (!array_key_exists($uname, $config['users'])) { $msg = '用户不存在'; return false; } $login_data = $config['users'][$uname]; if ($login_data[0] != $_POST['upwd']) { $msg = '密码错误!'; return false; } $_SESSION[$sess_id] = array('user_name' => $uname, 'rules' => isset($login_data[1]) ? $login_data[1] : false); return true; } /** * 用户登出操作 * @param string $sess_id * @return boolean * @since 1.0 <2015-10-9> SoChishun Added. */ static function user_logout($sess_id) { if (isset($_SESSION[$sess_id])) { unset($_SESSION[$sess_id]); } return true; } /** * 删除路径(文件或目录) * @param string $path 路径 * @param string $msg 错误消息 * @return boolean|string * @since 1.0 <2015-10-7> SoChishun Added. * @since 2.0 <2015-10-8> SoChishun 将delete_file和delete_dir合并到delete_path */ static function act_delete_path($path, &$msg = '') { if ('yes' != I('do')) { // 为防止黑客破坏,删除操作需要手动增加参数do=yes $msg = '非法操作!'; return false; } if ('/' == $path) { $msg = '根目录无法删除!'; return false; } $path = path_rtoa($path); if (is_file($path)) { if (!@unlink($path)) { $msg = '文件删除失败!'; return false; } return true; } if (is_dir($path)) { if (!@rmdir($path)) { $msg = '目录删除失败!(非空目录或权限不足)'; return false; } return true; } $msg = '不是有效文件或目录!'; return false; } /** * 保存(新)文件 * @param type $msg * @return boolean * @since 1.0 <2015-10-7> SoChishun Added. */ static function act_save_file(&$msg = '') { $filename = I('filename'); if (!$filename || !strpos($filename, '.')) { $msg = '文件扩展名无效!'; return false; } $content = I('content'); $path = I('path'); $path = path_rtoa($path); if (is_file($path)) { $path = path_getdir($path, false); } $newpath = $path . DIRECTORY_SEPARATOR . $filename; try { file_put_contents($newpath, $content); return true; } catch (Exception $ex) { $msg = $ex->getMessage(); return false; } } /** * 保存新目录 * @param string $msg 错误消息 * @return boolean * @since 1.0 <2015-10-8> SoChishun Added. */ static function act_save_newdir(&$msg = '') { $filename = I('filename'); if (!$filename) { $msg = '目录名称无效'; return false; } $path = path_rtoa(I('path')); $newpath = $path . DIRECTORY_SEPARATOR . $filename; try { mkdir($newpath, I('mode')); return true; } catch (Exception $ex) { $msg = $ex->getMessage(); return false; } } /** * 上传文件 * @param type $msg * @return boolean * @since 1.0 <2016-9-13> SoChishun Added. */ static function act_upload_file(&$msg = '') { if ($_FILES["file"]["error"] > 0) { $msg = $_FILES["file"]["error"]; return false; } $path = I('path'); $path = path_rtoa($path); $filename = $_FILES["file"]["name"]; if (file_exists($path . $filename)) { $msg = $filename . " 文件已存在!"; return false; } move_uploaded_file($_FILES["file"]["tmp_name"], $path . $filename); return true; } /** * 重命名路径操作 * @param string $msg 错误消息 * @return boolean * @since 1.0 <2015-10-9> SoChishun Added. */ static function act_rename_path(&$msg = '') { $filename2 = I('filename2'); if (!$filename2) { $msg = '新名称未填写!'; return false; } $path = path_rtoa(I('path')); if (is_file($path) && !strpos($filename2, '.')) { $msg = '文件扩展名无效!'; return false; } try { $newname = pathinfo($path, PATHINFO_DIRNAME) . DIRECTORY_SEPARATOR . $filename2; @rename($path, $newname); return true; } catch (Exception $ex) { $msg = $ex->getMessage(); return false; } } /** * 编辑权限操作 * @param string $msg 错误消息 * @return boolean * @since 1.0 <2015-10-9> SoChishun Added. */ static function act_chmod_path(&$msg = '') { $mode = I('mode'); if (!$mode) { $msg = '权限模式无效!'; return false; } $path = path_rtoa(I('path')); try { chmod($path, $mode); return true; } catch (Exception $ex) { $msg = $ex->getMessage(); return false; } } /** * 压缩操作 * @param string $msg * @return boolean * @since 1.0 <2015-10-9> SoChishun Added. */ static function act_zip(&$msg = '') { $filename = I('filename'); $content = I('content'); if (!$filename || !strpos($filename, '.')) { $msg = '压缩文件名无效!'; return false; } if (!$content) { $msg = '压缩内容无效!'; return false; } $include = array(); $exclude = array(); $paths = explode(PHP_EOL, $content); foreach ($paths as $path) { if (0 === strpos($path, 'exclude ')) { $exclude[] = trim(substr($path, 8)); } else { $include[] = $path; } } if (!$include) { $msg = '压缩内容无效!'; return false; } $zip = new ZipHelper(); return $zip->zip($filename, $msg, $include, $exclude, I('rootpath')); } /** * 解压缩文件 * @param type $msg * @return type */ static function act_unzip(&$msg = '') { $root = I('root'); $filename = I('filename'); if (!$filename) { $msg = '压缩文件路径无效!'; return false; } if (!$root) { $msg = '解压缩路径无效!'; return false; } $zip = new ZipHelper(); return $zip->unzip($filename, $root, $msg); } /** * 目录内容视图 * @param type $path * @since 1.0 <2015-5-11> SoChishun Added. */ static function view_content_list($path) { $files = self::get_dir_contents($path, array('name' => true, 'path' => false, 'real_path' => false, 'relative_path' => true, 'exten' => false, 'ctime' => false, 'mtime' => false, 'size' => false, 'is_dir' => true, 'is_file' => false, 'is_link' => true, 'is_executable' => true, 'is_readable' => false, 'is_writable' => false, 'filetype' => true)); echo 'SuExplorer-<?php echo $version ?> <?php if ($login_data): ?>class="userbar"> 欢迎您, <?php echo $login_data['user_name'] ?> "?action=logout">注销 "?view=newfile&path=<?php echo $parent_path ?>">新建文件 "?view=upload&path=<?php echo $parent_path ?>">上传文件 "?view=newdir&path=<?php echo $parent_path ?>">新建目录 "?view=zip&path=<?php echo $parent_path ?>">打包目录 "?view=unzip&path=<?php echo $parent_path ?>">解压目录<?php SuExplorer::index($view, $path) ?><?php else: ?>
';
foreach ($files as $file) {
if ($file['is_dir']) {
echo '' . $file['relative_path'] . '" class="blue">' . $file['name'] . '';
} else {
$class = '';
if ($file['is_link']) {
$class = 'lightblue';
} else if ($file['is_executable']) {
$class = 'green';
} else {
switch ($file['filetype']) {
case 'zip':
$class = 'red';
break;
case 'image':
$class = 'purple';
break;
default:
$class = 'grey';
break;
}
}
echo '' . $file['relative_path'] . '" class="' . $class . '">' . $file['name'] . '';
}
}
echo '
';
}
/**
* 文件内容编辑视图
* @param type $path
* @since 1.0 <2015-5-11> SoChishun Added.
*/
static function view_edit_file($path) {
$sapath = path_rtoa($path);
if (!is_file($sapath)) {
return;
}
$category = get_exten_catetory(pathinfo($path, PATHINFO_EXTENSION));
switch ($category) {
case 'doc':
case 'script':
$btns = '';
if (!is_writable($sapath)) {
echo '文件不可写
';
$btns = '';
}
echo ''; echo basename($path); echo ' ', $path, '" target="_blank">[原图]'; break; default: echo basename($path); echo ' ', $path, '" target="_blank">[下载]'; break; } } /** * 新增文件视图 * @param string $path 路径 * @since 1.0 <2015-10-8> SoChishun Added. */ static function view_create_file($path) { echo '