使用php实现一个简单的文件、图片管理器
最近项目需求需要一个图片管理器,用作编辑数据时可以直接选择图片,所以就写了个简单的文件管理器,最终想要实现
直接上代码好了,下面是获取当前目录下的文件、文件夹列表
/** * 获取当前目录下的内容 * @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上面,各位如果感兴趣的话也可以根据本文进行更改,需要对getDirectoryContents、upload、remove方法进行调整;下载资源中已附上上传管理阿里云OSS
源码下载:
版权声明:本文由“憨小猪”发布,如需转载请注明出处。



