# file-manage **Repository Path**: cwyay/file-manage ## Basic Information - **Project Name**: file-manage - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2026-09-09 - **Last Updated**: 2026-09-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 文件管理系统 一个基于 NestJS + React + Ant Design 的轻量级文件管理系统,用于管理**部署服务器上的实际文件系统**。 - 后端:NestJS + TypeScript,直接读写服务器本地磁盘 - 前端:React 18 + Ant Design 5 + TypeScript - 大文件:分片上传 + 断点续传 - 文件夹下载:流式打包成 ZIP - 无数据库:元数据从文件系统实时读取 --- ## 目录结构 ``` file-manage/ ├── server/ # NestJS 后端 ├── web/ # React + AntD 前端 ├── start.js # 一键启动脚本(跨平台) ├── docker-compose.yml # 容器化部署 └── README.md # 本文档 ``` --- ## 快速启动 ### 编译脚本 + 启动脚本(推荐) 启动拆分为两步:先编译(`build.js`,负责装包与构建),再启动(`start.js`,仅启动)。 ```bash # 1) 编译:装包(按需)+ 构建 node build.js # 后端每次必编;前端仅在 web/dist 不存在时才编译 node build.js --force # 强制重新编译前端 # 2) 启动 node start.js # 生产模式(单服务部署) node start.js --dev # 开发模式(后端 watch + 前端 vite dev server) ``` | 脚本 | 参数 | 说明 | | ---------- | --------- | ------------------------------------------------------------------------------------------ | | `build.js` | (无) | 后端每次必编;前端按源码修改时间判断(源码更新才重编);依赖仅当 `node_modules` 缺失时安装 | | `build.js` | `--force` | 强制重新编译前端(后端本来就每次都编) | | `start.js` | (无) | 生产模式,单服务部署,访问 `http://localhost:4321` | | `start.js` | `--dev` | 开发模式,后端 watch + 前端热更新,前端访问 `http://localhost:5173` | **`build.js` 装包 / 编译策略:** - 装包:仅当对应 `node_modules/` 不存在时才执行 `npm install` - 后端:每次都执行 `npm run build`(无论 `dist` 是否存在) - 前端:比较源码(`web/src` 等)与 `web/dist` 的最新修改时间 - `web/dist` 不存在 → 编译 - 源码未比产物更新 → 跳过(避免无意义的重复编译) - 源码已更新(如 `git pull` 后)→ **自动重新编译**,避免产物过期导致“新功能看不到” - `--force` 可强制重建 > 首次运行或 `git pull` 后:直接 `node build.js`(前端会在源码变更时自动重编),再 `node start.js`。 > `start.js` 启动前会检查产物 / 依赖是否就绪,缺失时提示先运行 `node build.js`。 ### 手动启动 ```bash # 1. 安装依赖 cd server && npm install && cd ../web && npm install # 2. 构建 cd server && npm run build && cd ../web && npm run build # 3. 启动(生产模式 — 后端托管前端) cd server && npm run start:prod # 访问 http://localhost:4321 # 或:开发态分开启动 cd server && npm run start:dev # 终端 1 cd web && npm run dev # 终端 2,访问 http://localhost:5173 ``` ### 环境变量 | 变量 | 默认值 | 说明 | | ---------------------------- | ---------------------------------------------------- | -------------------------------------------- | | `STORAGE_ROOT` | `/` | 文件管理根目录,默认管理服务器根目录 | | `PORT` | `4321`(见 `server/src/config/server.config.ts`) | 后端服务端口,也可通过环境变量覆盖 | | `HOST` | `0.0.0.0`(见 `server/src/config/server.config.ts`) | 监听地址,`0.0.0.0` 即监听所有网卡 | | `UPLOAD_STALE_TTL_MS` | `86400000`(24h) | 超过该时长未更新的上传会话视为孤儿,可被清理 | | `UPLOAD_CLEANUP_INTERVAL_MS` | `3600000`(1h) | 孤儿分片后台扫描间隔 | > **修改管理范围:** > > ```bash > # 默认启动即管理服务器根目录 / > node start.js > > # 如需限制范围,只管理某个目录: > STORAGE_ROOT=/home/user/projects node start.js > STORAGE_ROOT=/var/log node start.js > ``` > > 根目录本身**禁止删除**(防止误删整个服务器),但子目录和文件的删除不受限制。 ### 删除保护 | 受保护对象 | 是否禁止删除 | 说明 | | ---------------- | ------------ | ------------------------------------------------------------------------------- | | 存储根目录 `/` | ❌ 禁止 | 防止误删整个服务器 | | 系统关键目录 | ❌ 禁止 | `/etc` `/usr` `/bin` `/System` `/Library` `/Users` `/home` 等(仅一级目录本身) | | 系统目录下的子项 | ✅ 允许 | 如 `/etc/passwd`、`/Users/xxx` 可正常删除 | > 浏览、查看、上传、下载、重命名、移动等读/写操作对所有目录均开放;删除保护仅针对系统关键目录本身。 ### 命令终端 终端采用「一次性执行 + SSE 流式输出」模式,基于 `child_process` 启动命令,不支持交互式 TTY(vim、top、python REPL 等已在黑名单拦截)。 **命令搜索路径(PATH):** 后端启动子 shell 时,PATH 由三部分拼接,确保常用命令都能找到: 1. 当前进程的真实 `process.env.PATH`(保留服务器实际环境,如 nvm 注入的路径) 2. 配置项 `TERMINAL_PATH`(系统标准目录兜底) 3. npm 全局 bin 目录(由 `npm prefix -g` 解析出的 `bin`,即全局 CLI 的落点) 因此通过 `npm install -g` 安装的命令(如 `forever`、`pm2`、`typescript`)无需额外配置即可在终端中直接调用。 ### 目录路由(地址栏) 前端用 `react-router-dom` 把当前目录映射到地址栏路由,而非 `?path=` 查询参数: - 当前目录:`/browse/usr/bin`(直接分享 / 收藏) - 根目录:`/`(自动重定向到 `/browse`) - 浏览器**前进 / 后退**可在历史目录间穿梭 - 刷新页面后停留在当前目录(从路由恢复) 后端无需改动:NestJS 的 `*` 兜底路由对任意非 `/api` 路径都返回 `index.html`,刷新 `/browse/usr/bin` 时由前端路由接管。 --- ## 后端 API ### 文件浏览 | 方法 | 路径 | 说明 | | ------ | ------------------------------ | ----------------------- | | GET | `/api/files?path=/sub` | 列目录内容 | | GET | `/api/files/stat?path=...` | 单文件/目录元信息 | | POST | `/api/files/mkdir` | 创建目录 | | POST | `/api/files/move` | 移动/重命名 | | DELETE | `/api/files?path=...` | 删除文件或目录(递归) | | GET | `/api/files/download?path=...` | 下载文件或 ZIP 打包目录 | ### 分片上传 | 方法 | 路径 | 说明 | | ------ | ------------------------------------------ | ------------------------------------ | | POST | `/api/upload/init` | 初始化上传会话,返回 uploadId | | POST | `/api/upload/chunk?uploadId=...&index=...` | 上传单个分片(multipart) | | POST | `/api/upload/merge` | 合并所有分片 | | GET | `/api/upload/status?uploadId=...` | 查询已上传分片 | | DELETE | `/api/upload/cancel` | 取消并清理会话 | | POST | `/api/upload/cleanup` | 手动触发孤儿分片清理(返回清理数量) | ### 解压 / 目录树 | 方法 | 路径 | 说明 | | ---- | -------------------------------------------- | ------------------------------------------------------------------------------------------ | | POST | `/api/archive/extract` | 解压 ZIP 到指定目录;`targetDir` 缺省时解压到 ZIP 同级、以 ZIP 名(去 `.zip`)命名的子目录 | | GET | `/api/archive/dirtree?path=...&maxDepth=...` | 目录树(用于「移动到」选择器,支持懒加载,默认深度 3) | --- ## 核心设计要点 ### 1. 路径安全 所有用户传入的 `path` 参数都经过 `PathSafe` 校验,防御目录穿越攻击(`../etc/passwd` 等)。绝对路径注入会被规范化为相对路径。根目录禁止删除、禁止设为系统根 `/`。 ### 2. 流式处理 - 单文件下载:`fs.createReadStream` → 响应流,内存 O(1) - 目录 ZIP 下载:`archiver` 直接 pipe 到响应流,**不生成临时 ZIP 文件**,内存 O(1) - 分片合并:逐片流式 append 到目标文件,避免内存爆炸 ### 3. 断点续传 前端计算文件 hash(小文件全量,大文件抽样),上传前调用 `init`。后端通过 hash 复用已有会话,已上传的分片直接跳过,网络中断后可继续上传。 ### 4. TypeScript 严格 后端和前端的 `tsconfig` 均开启 `strict: true`、`noUncheckedIndexedAccess: true`、`noImplicitOverride: true`。 ### 5. 孤儿分片定时清理 用户中途放弃上传、网络中断或页面异常关闭时,`.upload-tmp//` 下的分片会残留,长期占用磁盘。`UploadService` 在**模块启动时立即执行一次**清理,并随后以固定间隔(`UPLOAD_CLEANUP_INTERVAL_MS`,默认 1h)周期扫描: - `meta.json` 缺失或解析失败 → 损坏会话,直接清理 - `meta.updatedAt` 距当前超过 `UPLOAD_STALE_TTL_MS`(默认 24h)→ 视为未完成/已放弃,清理 - 正在进行的会话会持续刷新 `updatedAt`,**不会被误删** 清理失败仅记录告警,不影响上传服务本身;也可随时 `POST /api/upload/cleanup` 主动触发即时回收。 --- ## 测试 ### 后端单元测试 ```bash cd server npm test ``` 当前覆盖:路径安全工具 `PathSafe`(目录穿越、绝对路径注入、前缀严格匹配等)。 ### 端到端验证 ```bash # 启动后端并托管前端 cd server npm run build STORAGE_ROOT=/tmp/fm-data PORT=4321 npm run start:prod # 浏览器访问 http://localhost:4321 验证以下功能: # - 文件浏览 / 新建目录 / 重命名 / 移动 / 删除 # - 分片上传(含断点续传) # - 文件夹 ZIP 下载 # - 文件内容查看与编辑 # - 命令终端(SSE 流式输出) ``` --- ## 开发建议 - **不要** 把 `STORAGE_ROOT` 设为 `/` 或 `/etc` 等敏感目录 - **不要** 在生产环境暴露上传接口(除非做好鉴权),当前版本已预留 token 守卫位置,可扩展登录/权限 - 大文件上传时建议部署在 SSD 上,避免机械硬盘的并发 IO 瓶颈 - 前端已做体积优化:antd / 图标 / react / 工具 拆分为独立 chunk 提升缓存命中;终端(xterm)、文件查看器(CodeMirror)改为懒加载,首屏不再包含这两块重依赖 --- ## 后续可扩展方向 - 接入 JWT/OAuth 鉴权 - 文件预览(图片、PDF、文本、Markdown) - 多文件同时上传进度队列 - 操作日志审计