const express = require('express'); const router = express.Router(); const fs = require('fs').promises; const path = require('path'); const { getActualLogPath } = require('../utils/file-utils'); // 读取目录内容 router.get('/readdir', async (req, res) => { try { // 获取实际的日志目录路径 const logDirPath = await getActualLogPath(); // 安全检查 if (!logDirPath) { return res.status(403).json({ error: '无权访问该目录' }); } // 检查目录是否存在 try { const stats = await fs.stat(logDirPath); if (!stats.isDirectory()) { return res.status(400).json({ error: '指定的路径不是目录' }); } } catch (statError) { // 如果目录不存在,尝试创建它 if (statError.code === 'ENOENT') { try { await fs.mkdir(logDirPath, { recursive: true }); } catch (mkdirError) { console.error('创建日志目录失败:', mkdirError); return res.status(500).json({ error: '创建日志目录失败' }); } } else { throw statError; } } // 读取目录内容 const files = await fs.readdir(logDirPath); // 返回文件列表 res.json({ files }); } catch (error) { console.error('读取目录失败:', error); // 处理特定错误 if (error.code === 'ENOENT') { return res.status(404).json({ error: '目录不存在' }); } if (error.code === 'EACCES') { return res.status(403).json({ error: '没有权限访问目录' }); } res.status(500).json({ error: '读取目录失败', message: error.message }); } }); // 获取文件状态信息 router.get('/stat', async (req, res) => { try { const fileName = req.query.path; if (!fileName) { return res.status(400).json({ error: '未提供文件名' }); } // 获取实际的日志目录路径 const logDirPath = await getActualLogPath(); if (!logDirPath) { return res.status(403).json({ error: '无权访问该文件' }); } // 构建完整的文件路径 const filePath = path.join(logDirPath, fileName); // 安全检查:确保文件在日志目录内 if (!filePath.startsWith(logDirPath)) { return res.status(403).json({ error: '无权访问该文件' }); } // 获取文件状态 const stats = await fs.stat(filePath); // 返回文件信息 res.json({ size: stats.size, isFile: stats.isFile(), isDirectory: stats.isDirectory(), created: stats.birthtime, modified: stats.mtime, accessed: stats.atime, mtime: stats.mtime.toISOString() }); } catch (error) { console.error('获取文件状态失败:', error); // 处理特定错误 if (error.code === 'ENOENT') { return res.status(404).json({ error: '文件不存在' }); } if (error.code === 'EACCES') { return res.status(403).json({ error: '没有权限访问文件' }); } res.status(500).json({ error: '获取文件状态失败', message: error.message }); } }); // 读取文件内容 router.get('/readFile', async (req, res) => { try { const fileName = req.query.path; if (!fileName) { return res.status(400).json({ error: '未提供文件名' }); } // 获取实际的日志目录路径 const logDirPath = await getActualLogPath(); if (!logDirPath) { return res.status(403).json({ error: '无权访问该文件' }); } // 构建完整的文件路径 const filePath = path.join(logDirPath, fileName); // 安全检查:确保文件在日志目录内 if (!filePath.startsWith(logDirPath)) { return res.status(403).json({ error: '无权访问该文件' }); } // 只允许访问.log文件 if (!fileName.endsWith('.log')) { return res.status(403).json({ error: '只能访问日志文件' }); } // 获取文件状态 const stats = await fs.stat(filePath); // 检查文件大小,限制读取过大的文件 const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB if (stats.size > MAX_FILE_SIZE) { return res.status(413).json({ error: '文件过大,无法读取' }); } // 读取文件内容 const content = await fs.readFile(filePath, 'utf-8'); // 设置响应头 res.setHeader('Content-Type', 'text/plain; charset=utf-8'); // 返回文件内容 res.send(content); } catch (error) { console.error('读取文件内容失败:', error); // 处理特定错误 if (error.code === 'ENOENT') { return res.status(404).json({ error: '文件不存在' }); } if (error.code === 'EACCES') { return res.status(403).json({ error: '没有权限访问文件' }); } res.status(500).json({ error: '读取文件内容失败', message: error.message }); } }); module.exports = router;