# ul-disk **Repository Path**: ulthon/ul-disk ## Basic Information - **Project Name**: ul-disk - **Description**: ul-disk 是基于ThinkPHP6打造的网盘系统。PHP有很多优秀的网盘系统,然而他们都是插件化的、生态化的。ul-disk的定位是仅提供基本的网盘功能,并且试图提供更多的技术使用和部署范围。 - **Primary Language**: PHP - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 65 - **Forks**: 12 - **Created**: 2018-02-28 - **Last Updated**: 2026-06-30 ## Categories & Tags **Categories**: filemanager **Tags**: None ## README # uldisk 基于 ThinkPHP 8 的分布式分块存储引擎,提供 WebDAV 协议接入与 HTMX 管理后台。 ## 特性 - **分块存储**:4MB 分块 + MD5 内容寻址,相同内容全局只存一份 - **Hamming 路由**:按位置 MD5 与 chunk MD5 的 Hamming 距离选择最佳存储位置,距离相同时按权重降序 - **多驱动支持**:Local / SFTP / FTP / WebDAV 四种后端,基于 FlySystem 3.0 统一抽象 - **WebDAV 服务**:完整 SabreDAV 4.x 实现,通过 litmus 合规性测试(basic / copymove / http 全 PASS) - **零拷贝 MOVE/COPY**:目录移动仅改 path/pid,文件复制复用 chunk_md5 索引 - **HTMX 管理后台**:基于 ULUI 的零 JS 框架后台,单管理员架构 - **容量追踪**:每个存储位置实时记录 size_used,写入时按 size_limit 路由 - **引用计数**:删除文件时逐 chunk 计数,最后一个引用才真正物理删除 ## 架构 ``` +-------------------+ +-------------------+ +-------------------+ | 管理后台(admin) | | WebDAV 服务 | | 存储引擎 | | HTMX + ULUI | | SabreDAV 4.x | | ChunkStorage | | | | | | | | - 登录/验证码 | | - Basic Auth | | - 4MB 分块 | | - 位置 CRUD | | - PROPFIND/PUT | | - MD5 去重 | | - 文件浏览器 | | - MKCOL/MOVE | | - Hamming 路由 | | - 系统配置 | | - COPY/DELETE | | - 引用计数 | +-------------------+ +-------------------+ +-------------------+ | | | +-------------------------+-------------------------+ | +---------------+ | FlySystem 3 | +---------------+ | +---------+---------+---------+---------+ | | | | | Local SFTP FTP WebDAV ... ``` ## 技术栈 | 层 | 技术 | |---|---| | 框架 | ThinkPHP 8 (多应用模式:admin / webdav) | | 存储 | FlySystem 3.0 (local / sftp / ftp / webdav adapters) | | WebDAV | SabreDAV 4.x | | 后台 | HTMX + ULUI (//ului.top) | | 数据库 | MySQL (think-orm 4.0) | | 部署 | Docker (PHP-FPM + Nginx) | ## 快速开始 预构建镜像已发布到 Docker Hub(`ulthon/ul-disk`,支持 amd64/arm64 双架构),三种部署方式按需选择。 ### 方式一:一键启动(推荐,开箱即用) 仓库根目录的 `docker-compose.yml` 内含 uldisk + MySQL,首次启动自动初始化数据库(migrate + seed): ```bash docker compose up -d ``` 默认访问 http://localhost:8001/admin(admin / admin123,**首次登录后请立即修改密码**)。 自定义数据库密码/端口,在同级目录建 `.env` 覆盖(可选变量见 `docker-compose.yml` 头部注释)。 ### 方式二:docker run(单容器,自备 MySQL) ```bash docker run -d --name uldisk \ -p 8001:8000 \ -e DB_HOST=<你的MySQL地址> \ -e DB_NAME=uldisk -e DB_USER=root -e DB_PASS=<密码> -e DB_PORT=3306 \ -v uldisk_runtime:/var/www/html/runtime \ -v uldisk_data:/var/www/html/data/storage \ ulthon/ul-disk:latest ``` ### 方式三:生产部署(外部 MySQL) ```bash cd docker/prod cp .env.example .env # 配置外部 MySQL 连接 docker compose up -d ``` 生产栈仅拉取 uldisk 镜像(不含 MySQL),连接外部数据库实例。 ### 访问地址 | 服务 | URL(默认端口 8001) | 凭据 | |---|---|---| | 管理后台 | http://localhost:8001/admin | admin / admin123 | | WebDAV | http://localhost:8001/dav | admin / admin123(Basic Auth) | | S3 兼容 API | http://localhost:8001/s3 | admin 后台生成 Access Key(SigV4 鉴权) | ### 自动初始化说明 uldisk 镜像首次启动会自动完成数据库初始化(无需手动 migrate/seed): 1. 等待 MySQL 可达(默认超时 120s,可用 `DB_WAIT_TIMEOUT` 调整) 2. 执行 `php think migrate:run`(建表,phinx 幂等) 3. 执行 `php think seed:run`(建管理员 + 配置 + 默认空间,仅首次) 4. 写入 `runtime/.db_initialized` 标志文件,后续启动跳过 如需跳过自动初始化(已手动初始化的环境),设置环境变量 `SKIP_AUTO_INIT=1`。 ### 从源码构建(开发) 开发栈含热重载(绑定挂载源码)+ phpMyAdmin,适合二次开发: ```bash cd docker/dev && docker compose up -d # 首次需手动初始化(开发栈不走 entrypoint 自动初始化) docker exec uldisk-dev-uldisk-1 php think migrate:run docker exec uldisk-dev-uldisk-1 php think seed:run ``` 开发栈端口:8002(Web)/ 13306(MySQL)/ 18888(phpMyAdmin)。 ### 构建并推送自有镜像 ```bash # 多架构(amd64 + arm64)构建并推送到你的 Docker Hub 仓库 IMAGE_REPO=<你的用户名>/ul-disk ./scripts/build-docker.sh v1.0.0 ``` 前置:需先注册 qemu binfmt 支持 arm64 跨架构编译(`docker run --privileged --rm tonistiigi/binfmt --install arm64`)。详见 `scripts/build-docker.sh` 头部说明。 ## 项目结构 ``` app/ admin/ # 管理后台应用 controller/ # Auth/Index/Position/Browser/Config middleware/ # AdminAuth 会话校验 route/ # 路由 view/ # HTMX 视图(局部刷新) webdav/ # WebDAV 服务应用 auth/ # AdminBackend (Basic Auth) controller/ # SabreDAV Server 引导 fs/ # File/Directory/Node/RootCollection response/ # SabreDAV 与 ThinkPHP 响应桥接 route/ common/ # 公共模块 model/ # 7 个数据表模型 service/ # ConfigService storage/ # ChunkStorage / DriverFactory / PositionRuntime common.php # 全局辅助(str_to_bin 等) config/ # ThinkPHP 配置(仅数据库走 .env) database/ migrations/ # 7 张表的迁移 seeds/ # InitAdmin / InitConfig docker/ dev/ # 开发栈(源码热重载 + MySQL + phpMyAdmin) prod/ # 生产栈(image 模式,外部 MySQL) docker-compose.yml # 开箱即用(预构建镜像 + MySQL) scripts/ build-docker.sh # 多架构镜像构建推送脚本 source/docker/ # nginx.conf / PHP 运行时配置 / docker-entrypoint.sh ``` ## WebDAV 客户端配置 WebDAV 服务兼容主流客户端,地址为 `http://:8001/dav`(默认端口,见所选部署方式),使用 Basic Auth(admin 账号)。 ### 已验证客户端 - Windows 资源管理器(映射网络驱动器) - macOS Finder(连接服务器) - Linux GVFS / davfs2 - Cyberduck / WinSCP / Rclone - litmus 合规性测试工具 ### 合规性测试结果 | 测试套件 | 通过 / 总数 | |---|---| | basic | 16 / 16 | | copymove | 13 / 13 | | http | 4 / 4 | | props | 11 / 14(PROPPATCH 待优化) | | locks | 19 / 30(SabreDAV 锁语义限制) | ## 开发指南 ### 启用调试 `config/trace.php` 控制调试栏(默认关闭)。需要调试时改为 `enable => true`。 ### 存储位置配置 在管理后台「存储位置」新建,选择驱动类型(Local/SFTP/FTP/WebDAV)并填写对应配置。每个位置会自动计算 MD5 指纹用于 Hamming 路由。 ### 核心算法说明 - **分块大小**:固定 4MB(`ChunkStorage::getChunkSize()`) - **路由策略**:Hamming 距离升序 → 权重降序 → 第一个可用位置(单副本) - **去重粒度**:chunk 级别(4MB),相同 MD5 的 chunk 全局只物理存一份 - **容量计数**:仅物理新写入累加 size_used,物理去重命中不计 ## 版权信息 本项目基于 ThinkPHP 8 框架开发,遵循 Apache-2.0 开源协议。 ThinkPHP 版权所有 Copyright © 2006-2024 by ThinkPHP (http://thinkphp.cn) 更多细节参阅 [LICENSE.txt](LICENSE.txt)。