php+vue3+tailwind实现简洁大气文件管理系统代码

代码语言:php

所属分类:文件

代码描述:php+vue3+tailwind实现简洁大气文件管理系统代码

代码标签: php vue tailwind 简洁 大气 文件 管理 系统 代码

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<?php
// ==========================================
// 后端 API 逻辑 (兼容 PHP 5.4)
// ==========================================

// 配置:指定服务器上的目录(建议使用绝对路径,或者相对于此脚本的路径)
 $BASE_DIR = __DIR__ . '/uploads/';


// 如果目录不存在则退出
if (!is_dir($BASE_DIR)) {
    die("404" . $BASE_DIR);
}

// 安全检查:防止目录穿越,确保路径在 BASE_DIR 内
function get_safe_path($relative_path, $base_dir) {
    $relative_path = trim($relative_path);

    // 空路径表示根目录
    if ($relative_path === '') {
        $real_base = realpath($base_dir);
        return $real_base ? $real_base : false;
    }

    // 检查空字节注入
    if (strpos($relative_path, "\0") !== false) {
        return false;
    }

    // 替换反斜杠为正斜杠
    $relative_path = str_replace('\\', '/', $relative_path);

    // 去除前导斜杠,防止拼接到绝对路径
    $relative_path = ltrim($relative_path, '/');

    // 检查路径穿越(包括编码绕过)
    if (strpos($relative_path, '..') !== false) {
        return false;
    }

    $real_base = realpath($base_dir);
    if ($real_base === false) {
        return false;
    }

    // 拼接绝对路径
    $absolute_path = $real_base . '/' . $relative_path;

    // 规范化:移除多余斜杠
    $absolute_path = preg_replace('#/+#', '/', $absolute_path);

    // 如果路径已存在,用 realpath 验证
    if (file_exists($absolute_path)) {
        $real_path = realpath($absolute_path);
        if ($real_path === false) return false;
        // 确保在 base_dir 内
        if (strpos($real_path, $real_base) !== 0) {
            return false;
        }
        // 额外检查:防止 /base/abcde 被 /base/abc 前缀匹配
        if (strlen($real_path) > strlen($real_base) && substr($real_path, strlen($real_base), 1) !== '/') {
            return false;
        }
        return $real_path;
    }

    // 路径不存在时,验证拼接后的路径是否在 base_dir 内
    if (strpos($absolute_path, $real_base) !== 0) {
        return false;
    }
    if (strlen($absolute_path) > strlen($real_base) && substr($absolute_path, strlen($real_base), 1) !== '/') {
        return false;
    }

    return $absolute_path;
}

// 递归删除目录
function deleteDir($dir) {
    if (!is_dir($dir)) return false;
    $items = scandir($dir);
    foreach ($items as $item) {
        if ($item == '.' || $item == '..') continue;
        $path = $dir . '/' . $item;
        if (is_dir($path)) {
            deleteDir($path);
        } else {
            unlink($path);
        }
    }
    return rmdir($dir);
}

// 过滤文件名中的非法字符
function sanitize_filename($name) {
    $name = basename($name);
    $name = str_replace("\0", '', $name);
    $name = trim($name);
    if ($name === '' || $name === '.' || $name === '..') {
        return false;
    }
    // 过滤非法字符(跨平台安全)
    if (preg_match('/[\/\\\\:*?"<>|]/', $name)) {
        return false;
    }
    return $name;
}

// 路由
 $action = isset($_GET['action']) ? $_GET['action'] : '';

if ($action !== '') {
    header('Content-Type: application/json; charset=utf-8');

    switch ($action) {
        case 'list':
            $path = isset($_GET['path']) ? $_GET['path'] : '';
            $safe_path = get_safe_path($path, $BASE_DIR);

            if (!$safe_path || !is_dir($safe_path)) {
                echo json_encode(array('code' => 400, 'msg' => '无效目录'));
                break;
            }

            $files = array();
            $items = scandir($safe_path);
            foreach ($items as $item) {
                if ($item == '.' || $item == '..') continue;

                $full_path = $safe_path . '/' . $item;
                $rel_path = ltrim(str_replace(realpath($BASE_DIR), '', $full_path), '/');

                $files[] = array(
                    'name' => $item,
                    'path' => $rel_path,
                    'is_dir' => is_dir($full_path),
                    'size' => is_file($full_path) ? filesize($full_path) : 0,
                    'mtime' => date('Y-m-d H:i:s', filemtime($full_path))
                );
            }
            echo json_encode(array('code' => 200, 'data' => $files, 'current_path' => $path));
            break;

        case 'upload':
            $path = isset($_POST['path']) ? $_POST['path'] : '';
            $relative_path = isset($_POST['relative_path']) ? $_POST['relative_path'] : '';
            $safe_base = get_safe_path($path, $BASE_DIR);

            if (!$safe_base || !is_dir($safe_base)) {
                echo json_encode(array('code' => 400, 'msg' => '上传目录无效'));
                break;
            }

            if (!isset($_FILES['file']) || $_FILES['file']['error'] > 0) {
                echo json_encode(array('code' => 400, 'msg' => '上传失败'));
                break;
            }

            if ($relative_path) {
                // 文件夹上传模式:relative_path 包含文件夹内部结构
                $relative_path = str_replace('\\', '/', $relative_path);
                $relative_path = ltrim($relative_path, '/');

                // 检查路径穿越
                if (strpos($relative_path, '..&#.........完整代码请登录后点击上方下载按钮下载查看

网友评论0