王新阳

wangxinyang

批量获取某目录及子孙目录下的所有图片image、视频video、目录dir、目录树dir_tree

/**
 * 批量获取某目录及子孙目录下的所有图片image、视频video、目录dir、目录树dir_tree
 * @param array  $filter_array 要过滤的目录名称列表
 */
function get_file_list($type, $path, $filter_array=array()){
	if(!in_array($type, explode(',','image,video,dir,dir_tree')))return return_data(1,'类型错误:'.$type);

	/**
	 * SELF_FIRST 目录从浅到深返回
	 * CHILD_FIRST 先处理子节点,目录从深到浅返回
	 */
	$iterator = new RecursiveIteratorIterator(
		new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS),
		RecursiveIteratorIterator::SELF_FIRST
	);

	$photos = [];
	$videos = [];
	$dirs = [];
	foreach ($iterator as $SplFileInfo){
		$skip=false;
		foreach($filter_array as $filter){
			if(strpos($SplFileInfo->getRealPath(), $filter)!==false){
				$skip=true;
				break;
			}
		}
		if($skip)continue;
/*
$SplFileInfo 实际是 RecursiveDirectoryIterator 类
参考:https://www.php.net/manual/zh/class.recursivedirectoryiterator.php
常用方法:
getExtension	获取扩展名,如:jpg
getFilename		获取文件名,如:abc.jpg
getPathname		返回创建 SplFileInfo 对象时传入的原始路径字符串(不做任何解析或验证),如:D:\web/pictures\2001\a.jpg
getRealPath		返回文件的规范化的绝对路径,如:D:\web\pictures\2001\a.jpg
getSize
getType
isDir
isFile
isLink	快捷方式,会自动跟随与链接文件
*/
		if($SplFileInfo->isDir()){
			$dirs[$iterator->getDepth()][] = $SplFileInfo->getRealPath();
		}else if($SplFileInfo->isFile()){
			$cur_path = dirname($SplFileInfo->getRealPath());
			$cur_file = $SplFileInfo->getRealPath();
			$cur_size = $SplFileInfo->getSize();
			switch(strtolower($SplFileInfo->getExtension())){
				case 'jpe':
				case 'jpg':
				case 'jpeg':
				case 'png':
					//因生成缩略图时可能出错,所以不展示大图片
					if($cur_size < 20*1024*1024){
						$photos[$cur_path][] = $cur_file;
					}
					break;
				case 'mp4':
					$videos[$cur_path][] = $cur_file;
					break;
			}
/*
			$photos[] = [
				'getRealPath' => $SplFileInfo->getRealPath(),
				'getPathname' => $SplFileInfo->getPathname(),
				'getExtension' => $SplFileInfo->getExtension(),
				'getFilename' => $SplFileInfo->getFilename(),
				'getSize' => $SplFileInfo->getSize(),
				'getType' => $SplFileInfo->getType(),
			];
*/
		}
	}
	ksort($dirs);
	// 构建树形结构
	$dir_tree = [];
	foreach ($dirs as $depth => $paths) {
		foreach ($paths as $path) {
			insertPathIntoTree($dir_tree, $path, $path);
		}
	}
	switch($type){
		case 'image':
			return return_data(0,'',$photos);
		case 'video':
			return return_data(0,'',videos);
		case 'dir':
			return return_data(0,'',dir);
		case 'dir_tree':
			return return_data(0,'',dir_tree);
	}
}
//生成目录树
function insertPathIntoTree(&$tree, $currentPath, $rootPath) {
  // 计算相对路径
  $relativePath = substr($currentPath, strlen($rootPath));
  if (empty($relativePath)) {
    $tree[$currentPath] = [];
    return;
  }

  // 分割路径
  $parts = explode(DIRECTORY_SEPARATOR, trim($relativePath, DIRECTORY_SEPARATOR));

  // 找到父路径
  $parentPath = $rootPath;
  for ($i = 0; $i < count($parts) - 1; $i++) {
    $parentPath .= DIRECTORY_SEPARATOR . $parts[$i];
  }

  // 如果是根目录下的直接子目录
  if ($parentPath === $rootPath) {
    $tree[$currentPath] = [];
    return;
  }

  // 在树中找到父路径对应的节点
  $current = &$tree;
  $pathSoFar = $rootPath;

  for ($i = 0; $i < count($parts) - 1; $i++) {
    $pathSoFar .= DIRECTORY_SEPARATOR . $parts[$i];
    // 查找当前路径在树中的位置
    $found = false;
    foreach ($current as $key => $value) {
      if (strpos($key, $pathSoFar) === 0) {
        $current = &$current[$key];
        $found = true;
        break;
      }
    }
    if (!$found) break;
  }

  // 在父节点中添加当前路径
  $current[$currentPath] = [];
}
2026-01-17
2026-01-20 星期二 农历腊月初二