网页文件浏览器总共 4 个文件实现:
支持打开并编辑的文本文件和配置文件:txt、log、conf、sql、ini和sh文件;
支持浏览的图片文件,php 支持的 gd 库打开的图片文件 jpeg、png、gif、bmp、wbmp、webp、xbm、xpm;
支持浏览的视频文件,h5 支持的 mp4、webm文件;
支持浏览的音乐文件,h5 支持的 mp3、wav 和 ogg 文件。
可以作为服务器端配置文件修改和文件浏览。但入口文件注意要改名或再做一个登录界面后进入。要注意编码问题,不要把服务器给改废!!
在移动端的程序执行效果:
视频文件应存放在站点根目录以内,否则会播放出错,如果需要更复杂的视频应用,应该借助FFMPEG来实现,这里没有使用FFMPEG软件。
index.php文件:
<?php /* php网页版文件浏览器 〈view 部分〉 作者:九天一声啸 邮箱:[email protected] 日期:2020.8.10 */ session_start(); //注意,此代码前不允许有任何输出,包括空白字符 //自动加载类文件 spl_autoload_register(function ($class) { $classPath = __DIR__. \'/\'.$class.\'.class.php\'; if(file_exists($classPath)){ include $classPath; }else{ die(\'类文件加载失败!\'); } }); $obj = new Manager; //加载到视图文件的图标变量 $person = $obj->icon[\'person\']; ?> <!DOCTYPE html> <html> <head> <title>php网页版文件浏览器</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/css/bootstrap.min.css"> <script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script> <script src="https://cdn.staticfile.org/popper.js/1.12.5/umd/popper.min.js"></script> <script src="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/js/bootstrap.min.js"></script> <style> .file-size{ float: right; color: #89a } .file-name{ display:inline-block; vertical-align: middle; margin-top:-12px } #edit{ padding: 6px; border: solid 1px #789; background-color: #fffabe; text-align: left; white-space: nowrap; overflow: scroll; } video{ margin:0px auto; } pre{ white-space:pre-wrap; white-space:-moz-pre-wrap; white-space:-o-pre-wrap; word-wrap:break-word; } </style> </head> <body> <div class="container"> <?php echo new Manager; ?> <div> <!-- 模态框 begin --> <div class="modal fade" id="myModal"> <div class="modal-dialog modal-full" role="document"> <div class="modal-content"> <!-- 模态框头部 --> <div class="modal-header"> <h4 class="modal-title">模态框头部</h4> <button type="button" class="close" data-dismiss="modal">×</button> </div> <!-- 模态框主体 --> <div class="modal-body" style="text-align:center"> 模态框内容.. </div> <!-- 模态框底部 --> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button> </div> </div> </div> </div> <!-- 模态框 end. --> <script> //图片点击事件 function pictureFunc(route){ $(".modal-title").html("图片显示:"); $(".modal-body").html("<img src=\'./image.php?url=" + route + "\' width=\'100%\'>"); $("#myModal").modal(); } //文本文件点击事件 function textFunc(str, url){ /* 用 php 的 urlencode 编码后,用 js 的 decodeURIComponent 解码 空格会产生 + 号。 处理方法:要先替换 + 号为空格,再转码; 否则,文字里的空格全是 + 号,并且与正常的 + 号无法区分 如:“这是个数学等式+3+++2+=+5+是否正确。” */ /////////////////////////////////////////////////////////////////// var str1 = str.replace(/\+/g, " "); var str2 = decodeURIComponent(str1); ////////////////////////////////////////////////////////////////// $(".modal-title").html("文字编辑:"); var content = [ \'<form action="" method="post">\', \'<input type="hidden" id="edit2url" name="edit2url" value="\' + url + \'">\', \'<pre><textarea id="edit" name="edit" style="overflow:auto;width:100%;height: 600px">\', str2, \'</textarea></pre><div style="text-align:center;padding-top:8px">\', \'<input type="submit" value="保存" class="btn btn-info">\', \'</div></form>\' ].join(""); $(".modal-body").html(content); $("#myModal").modal(); /* h5 的 web 存储功能,sessionStorage对象存储, 当用户关闭浏览器窗口后,数据会被删除。 存储当前 url 地址,在后端写入文件后,方便返回到当前 url 地址 */ if(typeof(Storage)!=="undefined"){ sessionStorage.urlname = location.href; }else{ alert("对不起,您的浏览器不支持 web 存储,有的功能无法使用!"); } } //视频文件点击事件,h5 只支持 mp4、webm、ogg三种文件格式, //因为 ogg 格式与音乐文件重叠,这里舍去了ogg 格式 function videoFunc(url, extention){ $(".modal-title").html("视频显示:"); var mp4 = [ \'<video width="320" height="240" controls>\', \'<source src="\', url, \'" type="video/mp4"></video>\' ].join(\'\'); var webm = [ \'<video width="320" height="240" controls>\', \'<source src="\', url, \'" type="video/webm"></video>\' ].join(\'\'); var default1 = [ \'<p style="color:red;text-align:center"><strong>\', \'h5页面不支持该文件显示!\', \'</strong></p>\' ].join(\'\'); switch(extention.trim()){ case "mp4": $(".modal-body").html(mp4); break; case "webm": $(".modal-body").html(webm); default: $(".modal-body").html(default1); } $("#myModal").modal(); } //音频文件点击事件,h5 只支持 mp3、wav、ogg 三种文件格式 function musicFunc(url, extention){ $(".modal-title").html("音频显示:"); var ogg = [ \'<audio controls>\', \'<source src="\', url, \'" type="audio/ogg"></audio>\' ].join(\'\'); var mp3 = [ \'<audio controls>\', \'<source src="\', url, \'" type="audio/mp3"></audio>\' ].join(\'\'); var wav = [ \'<audio controls>\', \'<source src="\', url, \'" type="audio/wav"></audio>\' ].join(\'\'); var default1 = [ \'<p style="color:red;text-align:center"><strong>\', \'h5页面不支持该文件显示!\', \'</strong></p>\' ].join(\'\'); switch(extention.trim()){ case "mp3": $(".modal-body").html(mp3); break; case "wav": $(".modal-body").html(wav); break; case "ogg": $(".modal-body").html(ogg); break; default: $(".modal-body").html(default1); } $("#myModal").modal(); } //未识别文件的点击事件 function otherFunc(){ $(".modal-title").html("未知文件?"); var other = [ \'<p style="color:red;text-align:center"><strong>\', \'<?=$person?>错误,不能识别此文件!\', \'</strong></p>\' ].join(\'\'); $(".modal-body").html(other); $("#myModal").modal(); } </script> </body> </html>
Manager.class.php文件:
<?php /*########################################*/ // php网页版文件浏览器(编辑服务器配置用) // // 〈controller 部分〉 // 本程序的关键函数是 glob() 请查阅 php 手册 // // 作者:九天一声啸 // 邮箱:[email protected] // 日期:2020.8.10 // /*########################################*/ class Manager{ private $dirDataStructure; // 对目录进行处理的数组,用于 glob() 函数的目录参数 private $dirArr; // glob() 函数获取到文件和目录的数组 private $icon; // 图标数组 private $startDir; public function __construct(){ //页面初始化时,显示程序目录的上一级目录 $arr = explode(\'/\', __DIR__); array_pop($arr); $this->startDir = implode(\'/\', $arr); if(isset($_SESSION["dir"])){ $this->dirDataStructure = $_SESSION["dir"]; }else{ $this->dirDataStructure = explode(\'/\', $this->startDir); } $obj = new Icon; $this->icon = $obj->getIcon(); } public function __toString(){ $this->request(); $this->dirAfter(); $this->dirFront(); $ret = $this->process(). $this->showDirs(). $this->showFiles(); return $ret; } /* after 变量携带的数据是 $this->dirDataStructure 属性数组的下标,用户点击页面顶部目录部分, 由 after 截取该数组 */ private function dirAfter(){ if(filter_input(INPUT_GET, "after", FILTER_VALIDATE_INT)){ if(isset($_GET["after"])){ $this->dirDataStructure = array_slice($this->dirDataStructure, 0, $_GET["after"]); $_SESSION["dir"] = $this->dirDataStructure; } } } /* front 变量携带的数据是目录名称,用户点击页面中部的目录图标,该变量向 $this->dirDataStructure 属性数组追加目录名称 */ private function dirFront(){ if(!isset($_GET["after"])){ if(!isset($_GET["front"])){ //如果 url 上没有变量 after 和 front 则显示当前程序所在目录 $this->dirDataStructure = explode(\'/\' , $this->startDir); }else{ if(filter_input(INPUT_GET, "front", FILTER_SANITIZE_STRING)){ //检查页面是否有刷新,刷新时数据不写入数组和 session $pageWasRefreshed = isset($_SERVER[\'HTTP_CACHE_CONTROL\']) && ($_SERVER[\'HTTP_CACHE_CONTROL\'] === \'max-age=0\'); if(!$pageWasRefreshed ) { $dirstr = implode(\'/\', $this->dirDataStructure) . \'/\'; //检查目录是否成在,成在时才写入数组和 session if(file_exists($dirstr . $_GET["front"])){ array_push($this->dirDataStructure, $_GET["front"]); $_SESSION["dir"] = $this->dirDataStructure; } } } } } } //文件写入的方法部分 private function request(){ if(isset($_POST["edit"]) && isset($_POST["edit2url"])){ /* 文件覆盖写入 注意:所有的特殊字符如 < > " \' 等都会转码, 字符串加入的代码内容会失效; 在文件写入时获得一个独占锁。 对尖括号 <> 进行转义。 */ file_put_contents(addcslashes($_POST[\'edit2url\'], \'<>\'), addcslashes($_POST[\'edit\'], \'<>\'), LOCK_EX); //返回到前端 web 存储的 url 地址 echo \'<script>location.href = sessionStorage.urlname;</script>\'; } } private function process(){ $i = 1; foreach($this->dirDataStructure as $dirName){ $param = preg_replace(\'/&.+$/\', \'\', $_SERVER[\'QUERY_STRING\']); $strToPage .= "<a href=\'" . htmlspecialchars($_SERVER["PHP_SELF"]) . \'?\' . $param . "&after={$i}\'>" . $dirName . \'/</a>\'; $strToGlob .= $dirName . \'/\'; $i++; } $title = <<<EOF <div class="alert alert-success" style="word-wrap:break-word"> <strong>选择目录:</strong> {$strToPage} </div> EOF; //上面一行必须顶到左边;并且不能有注释; //不能是文件最后一行,如果是最后一行,请再换一行空白行。 /* 这里修改 * 号为 *.txt、*.php 等,可查看指定后缀名的文件, 也可以做成文件搜索功能。这里显示全部文件。 */ $this->dirArr = glob($strToGlob . \'*\'); //数组排序 sort($this->dirArr); return $title; } //输出目录部分 private function showDirs(){ $shows = \'\'; foreach($this->dirArr as $value){ if(is_dir($value) && file_exists($value)){ //显示目录磁盘大小 $ds = 0; $ds = $this->dirSize($value); if($ds/1024/1024/1024 >= 1){ $dirSize = round($ds/1024/1024/1024, 2) . \'G\'; }elseif($ds/1024/1024 >= 1){ $dirSize = round($ds/1024/1024, 2) . \'M\'; }elseif($ds/1024 >= 1){ $dirSize = round($ds/1024, 2) . \'K\'; }else{ $dirSize = round($ds, 2) . \'B\'; } //用 svg 显示图标 $param = preg_replace(\'/&.+$/\', \'\', $_SERVER[\'QUERY_STRING\']); $show = \'<a href="\' . htmlspecialchars($_SERVER["PHP_SELF"]) . \'?\' . $param . \'&front=\' . basename($value) . \'">\' . $this->icon[\'dir\']; $show .= \'<span class="file-name"> \' . basename($value) . \'</span>\'; $show .= \'</a><span class="file-size">\' . $dirSize . \'</span><br>\'; $shows .= $show; } } return $shows; } //输出文件部分 private function showFiles(){ $shows = \'\'; foreach($this->dirArr as $value){ if(is_file($value)){ //获取转小写后的文件后缀名 $extention = strtolower(pathinfo($value, PATHINFO_EXTENSION)); $fileName = basename($value); //显示文件大小 $fs = 0; $fs = filesize($value); if($fs/1024/1024/1024 >= 1){ $fileSize = round($fs/1024/1024/1024, 2) . \'G\'; }elseif($fs/1024/1024 >= 1){ $fileSize = round($fs/1024/1024, 2) . \'M\'; }elseif($fs/1024 >= 1){ $fileSize = round($fs/1024, 2) . \'K\'; }else{ $fileSize = round($fs, 2) . \'B\'; } //如果文件名太长,截取文件名 //注意 $fileName 只能用于前端显示,不能用于后端的文件路径访问 if(mb_strlen(reset(explode(\'.\', $fileName))) > 18){ $fileName = reset(explode(\'.\', $fileName)); $fileName = substr($fileName, 0, 18) . \'···.\' . $extention; } //根据后缀名显示相关图标 switch($extention){ //图片文件的图标 case \'bmp\': case \'wbmp\': case \'webp\': case \'jpg\': case \'jpeg\': case \'png\': case \'gif\': case \'ico\': case \'xbm\': case \'xpm\': $show = $this->icon[\'picture\']; /* 支持文件打开的方法是加了个 onclick 事件函数 pictureFunc(绝对路径) 第一个参数:是图片的绝对路径 在前端用 <img src="./image.php?url=绝对路径" /> 转相对路径访问 */ $show .= \'<span class="file-name" onclick="pictureFunc(\\'\' . urlencode($value) . \'\\')"> \' . $fileName . \'</span>\'; $show .= \'<span class="file-size">\' . $fileSize . \'</span>\'; $show .= \'<br>\'; $shows .= $show; break; //视频文件的图标 case \'avi\': case \'wmv\': case \'mpeg\': case \'mpg\': case \'mov\': case \'rm\': case \'ram\': case \'swf\': case \'flv\': case \'mp4\': // h5 支持的格式 case \'webm\': // h5 支持的格式 $show = $this->icon[\'video\']; /* 支持文件打开的方法是加了个 onclick 事件函数 videoFunc(相对路径, 文件后缀名) 第一个参数:是网站根目下的相对路径, 注意:网站根目录外的文件无法访问 第二个参数:是后缀名 */ $show .= \'<span class="file-name" onclick="videoFunc(\\'\' . $this->absolute2relative($value) . \'\\', \\'\' . trim($extention) . \' \\')"> \' . $fileName . \'</span>\'; $show .= \'<span class="file-size">\' . $fileSize . \'</span>\'; $show .= \'<br>\'; $shows .= $show; break; // 音乐文件的图标 case \'mp1\': case \'mp2\': case \'wma\': case \'wmv\': case \'rm\': case \'rmvb\': case \'aac\': case \'mid\': case \'vqf\': case \'avi\': case \'mpg\': case \'mpeg\': case \'cda\': case \'mp3\': // h5 支持的格式 case \'wav\': // h5 支持的格式 case \'ogg\': // h5 支持的格式 $show = $this->icon[\'music\']; /* 支持文件打开的方法是加了个 onclick 事件函数 musicFunc(相对路径, 文件后缀名) 第一个参数:是网站根目下的相对路径, 注意:网站根目录外的文件无法访问 第二个参数:是后缀名 */ $show .= \'<span class="file-name" onclick="musicFunc(\\'\' . $this->absolute2relative($value) . \'\\', \\'\' . trim($extention) . \' \\')"> \' . $fileName . \'</span>\'; $show .= \'<span class="file-size">\' . $fileSize . \'</span>\'; $show .= \'<br>\'; $shows .= $show; break; //文本文件的图标 case \'txt\': case \'log\': case \'sql\': $show = $this->icon[\'text\']; $show .= \'<span class="file-name" \'; /* 支持文件打开的方法是加了个 onclick 事件函数 textFunc(文件内容, 绝对路径) 第一个参数:是 url 加密后的文件数据内容 需要注意的是:php url 加密后,用 js url 解密,空格会变成 + 号, 与正常的 + 号无法区分开来; 处理方法写在前端的 js 处理程序的注释部分 第二个参数:是文件绝对路径 */ $show .= \'onclick="textFunc(\\'\' . urlencode(file_get_contents($value)) . \'\\', \\'\' . $value . \'\\')"> \' . $fileName . \'</span>\'; $show .= \'<span class="file-size">\' . $fileSize . \'</span>\'; $show .= \'<br>\'; $shows .= $show; break; //配置文件的图标 case \'conf\': case \'ini\': case \'sh\': $show = $this->icon[\'configuration\']; /* 支持文件打开的方法是加了个 onclick 事件 调用的是文本文件事件函数 textFunc(文件内容, 绝对路径) 第一个参数:是 url 加密后的文件数据内容 第二个参数:是文件绝对路径 */ $show .= \'<span class="file-name" onclick="textFunc(\\'\' . urlencode(file_get_contents($value)) . \'\\', \\'\' . $value . \'\\')"> \' . $fileName . \'</span>\'; $show .= \'<span class="file-size">\' . $fileSize . \'</span>\'; $show .= \'<br>\'; $shows .= $show; break; //html文件的图标 case \'html\': case \'htm\': case \'shtml\': case \'shtm\': $show = $this->icon[\'html\']; /* 未识别文件 onclick 事件函数 otherFunc() */ $show .= \'<span class="file-name" onclick="otherFunc()"> \' . $fileName . \'</span>\'; $show .= \'<span class="file-size">\' . $fileSize . \'</span>\'; $show .= \'<br>\'; $shows .= $show; break; //代码文件的图标 case \'php\': case \'jsp\': case \'asp\': case \'aspx\': case \'cs\': case \'cpp\': case \'h\': case \'c\': $show = $this->icon[\'code\']; /* 未识别文件 onclick 事件函数 otherFunc() */ $show .= \'<span class="file-name" onclick="otherFunc()"> \' . $fileName . \'<
请发表评论