当前位置:首页 > 后端 > php > 使用php实现一个简单的文件、图片管理器

使用php实现一个简单的文件、图片管理器

DChen1年前 (2021-05-01)php5990

最近项目需求需要一个图片管理器,用作编辑数据时可以直接选择图片,所以就写了个简单的文件管理器,最终想要实现

的效果如下:(本文不提供前端代码,只讲后端接口实现)使用php实现一个简单的文件、图片管理器  php 文件管理器 php上传 OSS 第1张


直接上代码好了,下面是获取当前目录下的文件、文件夹列表

/**
 * 获取当前目录下的内容
 * @param string $marker
 * @return array
 */
public function getDirectoryContents(string $marker = '')
{
    // TODO: Implement getDirectoryContent() method.
    $curr_full_path = $this->getCurrFullPath();
    // 1、首先先读取文件夹
    $temp = scandir("." . $curr_full_path);
    //遍历文件夹
    $dirs = $files = [];
    foreach ($temp as $item) {
        $complete_path = $curr_full_path . $item;
        if (is_dir("." . $complete_path)) {
            if ($item == "." || $item == "..") {
                continue;
            }
            $dirs[] = [
                "type" => "folder",
                "path" => "{$this->curr_path}{$item}/",
                "name" => $item,
            ];
        } else {
            $info = $this->getFileInfo("." . $complete_path);
            $files[] = [
                'type' => $info['type'],
                'path' => $complete_path,//不带域名
                'name' => $item,
                'info' => $info,
            ];
        }
    }
    return array_merge($dirs, $files);
}


获取顶部面包屑:

/**
 * 获取当前目录的面包屑
 * @param string|null $filter_path 过滤该目录前的路径 eg:image/
 * @return array
 */
public function getCrumbs(?string $filter_path = null)
{
    $curr_path = $this->curr_path;
    $old_nodes = array_filter(explode('/', $curr_path));//原始路径节点
    $old_node_count = count($old_nodes);// 原始路径节点数
    if (!empty($filter_path)) {
        $curr_path = mb_substr($curr_path, (stripos($curr_path, $filter_path)));// 截取掉过滤路径前的部分
    }
    $nodes = array_filter(explode('/', $curr_path));//获得新的路径节点
    $node_count = count($nodes);//获得新的路径节点数
    $list = [];
    $j = 0;
    foreach ($nodes as $k => $node) {
        $list[$j]['name'] = $node;
        $list[$j]['path'] = '';
        $item = $old_node_count > $node_count ? $k + ($old_node_count - $node_count) : $k;
        for ($i = 0; $i <= $item; $i++) {
            if ($old_node_count > $node_count) {
                $list[$j]['path'] .= $old_nodes[$i] . '/';
            } else {
                $list[$j]['path'] .= $nodes[$i] . '/';
            }
        }
        $j++;
    }
    // 当存在过滤的情况下,可以将过滤的目录也卸载掉(比如:商家后台媒体根目录是"shop/shop_1234/",
    但实际"shop/shop_1234/"目录不需要展示在面包屑上)
    $filter_path_key = substr($filter_path, 0, strlen($filter_path) - 1);
    if (!empty($list) && $filter_path_key !== false && $list[0]['name'] == $filter_path_key) {
        unset($list[0]);
    }
    return array_values($list);
}


创建目录:

/**
 * 创建目录
 * @param string $name 目录名称
 * @return array
 * @throws Exception
 */
public function createFolder(string $name)
{
    $curr_full_path = $this->getCurrFullPath();
    $directory = $curr_full_path . $name;
    if (is_dir("." . $directory)) {
        return ['type' => 'folder', 'path' => $this->curr_path . $name . '/', 'name' => $name];
    }
    $res = mkdir('.' . $directory, 0755, true);
    if ($res) {
        return ['type' => 'folder', 'path' => $this->curr_path . $name . '/', 'name' => $name];
    }
    throw new \Exception("创建目录失败", 10000);
}


上传文件(上传视频或者较大的文件不建议采用这样写法,可以采用分片处理(推荐)或者put上传):

// 上传单个文件
public function upload()
{
    $_file = $_FILES;
    if (empty($_file)) {
        throw new Exception("请上传文件");
    }
    //处理存储目录
    $directory = $this->getCurrFullPath();
    try {
        //创建目录
        if (!is_dir('.' . $directory)) {
            if (!mkdir('.' . $directory, 0755, true)) {
                throw new \Exception("创建目录失败");
            }
        }
        foreach ($_file as $item) {
            if ($_FILES["image"]["error"] !== UPLOAD_ERR_OK) {
                throw new Exception("上传图片时出错:{$_FILES['image']['error']}");
            }
            $ext = pathinfo($item["tmp_name"])['extension'];
            if (!empty($this->ext)) {
                if (!in_array($ext, $this->ext)) {
                    throw new \Exception('上传失败,上传格式不支持');
                }
            }
            $info = $this->getFileInfo($item["tmp_name"]);
            if ($this->max_upload_size > 0 && ($item["tmp_name"]["size"]) > $this->max_upload_size) {
                $max_size = sprintf("%.2f", ($this->max_upload_size / (1024 * 1024)));
                throw new \Exception("上传失败,文件大小超过{$max_size}M");
            }
            $basename = bin2hex(random_bytes(8));
            $filename = sprintf('%s.%0.8s', $basename, $ext);//文件名称
            $save = $directory . $filename;//保存地址
            $res = move_uploaded_file($item["tmp_name"], '.' . $save);
            if (!$res) {
                throw new \Exception("上传失败");
            }
            return [
                'status' => true,
                'msg' => '上传成功',
                'data' => [
                    "type" => $info['type'],
                    'path' => $save,
                    'name' => $filename,
                    'info' => $info
                ]
            ];
            break;
        }
    } catch (Exception $e) {
        throw new \Exception($e->getMessage(), $e->getCode());
    }
}


删除:

/**
 *
 * @param string $path
 * @return bool
 */
public function remove(string $path)
{
    if (strrpos($path, "/") !== false) {
        if (strrpos($path, "/") == (strlen($path) - 1)) {
            $curr_full_path = $this->root_path . $path;
            if (is_dir("." . $curr_full_path)) {
                $dh = opendir("." . $curr_full_path);
                while ($file = readdir($dh)) {
                    if ($file != "." && $file != "..") {
                        $fullpath = $curr_full_path . $file;
                        if (!is_dir($fullpath)) {
                            unlink($fullpath);
                        } else {
                            $this->remove($fullpath);
                        }
                    }
                }
                closedir($dh);
                if(rmdir("." . $curr_full_path)) {
                    return true;
                } else {
                    return false;
                }
            }
        } else {
            if(@unlink($path)){
                return true;
            }else{
                return false;
            }
        }
    }
    return false;
}


其他相关的代码:

/**
 * 获取当前完整相对路劲
 * @return string
 */
protected function getCurrFullPath()
{
    return $this->curr_full_path = $this->root_path . $this->curr_path;
}

protected function getFileInfo($file)
{
    $info['type'] = "file";
    $info['size'] = sprintf("%.2f", filesize($file) / 1024);//kb
    if (function_exists("finfo_open") && function_exists("finfo_file")) {
        $res = finfo_open(FILEINFO_MIME_TYPE);
        $mime = finfo_file($res, $file);
        // 文件暂时只支持辨别image类型
        if ($mime !== false || stripos($mime, "image/") == 0) {
            list($info['width'], $info['height']) = getimagesize($file);
            $info['type'] = "image";
        }
    }
    return $info;
}


调试

$path = "supplier/supplier.1/test/"; // 以针对性目录,调用者根目录为"/supplier/supplier.1/"为准做调试.
$filter = "supplier.1";// 模拟平台下的商户只拥有指定"supplier.1"目录及子目录访问权限;平台可忽略该变量,则可在"upload/images/"下全部可管理
// 创建对象
$management = new LocalManagement('upload/images/', $path);// 本地文件管理器


获取面包屑:

// 获取面包屑
var_dump$(management->getCrumbs($filter));
// 打印结果
array(1) {
  [0]=>
  array(2) {
    ["name"]=>
    string(4) "test"
    ["path"]=>
    string(25) "supplier/supplier.1/test/"
  }
}


获取目录下的内容:

var_dump$(management->getDirectoryContents());
// 打印结果
array(2) {
  [0]=>
  array(3) {
    ["type"]=>
    string(6) "folder"
    ["path"]=>
    string(40) "/upload/images/supplier/supplier.1/test/"
    ["name"]=>
    string(4) "test"
  }
  [1]=>
  array(4) {
    ["type"]=>
    string(5) "image"
    ["path"]=>
    string(56) "/upload/images/supplier/supplier.1/0e38b2520594235a.jpeg"
    ["name"]=>
    string(21) "0e38b2520594235a.jpeg"
    ["info"]=>
    array(4) {
      ["type"]=>
      string(5) "image"
      ["size"]=>
      string(5) "31.69"//kb
      ["width"]=>
      int(997)//px
      ["height"]=>
      int(295)
    }
  }
}


创建目录:

var_dump$(management->createFolder('name'));
// 打印结果
array(3) {
  ["type"]=>
  string(6) "folder"
  ["path"]=>
  string(25) "supplier/supplier.1/name/"
  ["name"]=>
  string(4) "name"
}


上传文件:

var_dump$(management->upload('name'));
// 打印结果
array(3) {
  ["status"]=>
  bool(true)
  ["msg"]=>
  string(12) "上传成功"
  ["data"]=>
  array(4) {
    ["type"]=>
    string(5) "image"
    ["path"]=>
    string(55) "/upload/images/supplier/supplier.1/c4b30547f1390249.png"
    ["name"]=>
    string(20) "c4b30547f1390249.png"
    ["info"]=>
    array(4) {
      ["type"]=>
      string(5) "image"
      ["size"]=>
      string(6) "174.34"
      ["width"]=>
      int(512)
      ["height"]=>
      int(512)
    }
  }
}

本文上传、管理暂针对本地存储,后续有空将更新上传至阿里云的OSS上面,各位如果感兴趣的话也可以根据本文进行更改,需要对getDirectoryContentsuploadremove方法进行调整;下载资源中已附上上传管理阿里云OSS

源码下载:

此处内容需要评论后才能查看。
点击去评论



取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

版权声明:本文由“憨小猪”发布,如需转载请注明出处。

本文链接:https://www.phper.red/post/70.html

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。