简介
本文件为 DouPHP 提供“全面的文件备份解决方案”文档,覆盖用户上传的多媒体文件(图片、文档、视频等)、系统/模块/主题配置、模板与静态资源,以及增量备份策略、备份包组织命名规则、大文件性能优化、断点续传与错误重试机制,并给出自动化脚本与手动操作流程。
项目结构
DouPHP 的文件存储采用统一文件系统抽象,默认本地磁盘根为 images/upload,并通过 FilesystemManager 按约定或显式配置生成各业务磁盘;附件上传通过 Attachment 服务完成,支持分块上传与草稿模式;后台内置数据备份与恢复功能,支持 SQL 分卷导出、打包 images 目录为 zip、安全解压白名单控制。
graph TB
A["管理员界面<br/>backup.htm"] --> B["备份控制器<br/>BackupController"]
B --> C["备份服务<br/>BackupService"]
C --> D["数据库<br/>SQL 导出/导入"]
C --> E["压缩工具<br/>Zip::create/extract"]
C --> F["站点根目录 images/*<br/>附件资源"]
G["前台/后台上传入口<br/>UserController / 业务 Service"] --> H["附件服务<br/>AttachmentService/ChunkedUploadHandler"]
H --> I["文件系统门面<br/>Storage"]
I --> J["文件系统管理器<br/>FilesystemManager"]
J --> K["本地磁盘适配器<br/>LocalAdapter(images/*)"]
核心组件
- 备份控制器与服务:负责表清单构建、分卷 SQL 导出、zip 打包 images、恢复导入、删除与下载。
- 文件系统与存储:统一管理磁盘根、URL、上传策略,支撑附件落盘与路径解析。
- 附件上传:支持分块上传、草稿认领、缩略图与水印、类型校验与大小限制。
- 配置:系统基础配置、文件上传默认策略、云服务 API 基地址。
架构总览
下图展示从用户/后台上传到落盘,再到备份打包的完整链路。
sequenceDiagram
participant U as "用户/管理员"
participant UC as "前台控制器 UserController"
participant AS as "附件服务 AttachmentService"
participant CU as "分块上传 ChunkedUploadHandler"
participant FS as "文件系统 Storage/FilesystemManager"
participant BK as "备份服务 BackupService"
participant ZIP as "Zip 工具"
participant DB as "数据库"
U->>UC : 选择文件并提交
UC->>AS : store/storeDraft(带选项)
AS->>CU : handle(分片/合并/入库)
CU->>FS : 写入 images/{module}/...
Note over FS : 默认根 images/upload,按约定派生子目录
U->>BK : 触发备份(含 assets)
BK->>DB : 分卷导出 SQL
BK->>ZIP : 打包 SQL + images 目录
ZIP-->>U : 返回 zip 包
详细组件分析
备份控制器与服务
- 职责边界
- 控制器仅做请求转发与响应包装,具体逻辑在 Service。
- Service 负责:表清单、分卷 SQL 导出、zip 打包 images、恢复导入、删除与流式下载。
- 关键流程
- 备份:按表前缀列出表 → 分卷写入 SQL → 可选打包 images → 审计日志。
- 恢复:支持 zip 解压(白名单)→ 顺序执行多分卷 SQL → 清理临时文件 → 审计日志。
- 删除:二次确认 → 删除主文件及同前缀分卷。
- 下载:流式输出二进制内容。
- 安全要点
- 文件名严格校验,拒绝目录穿越与非法扩展名。
- 解压白名单仅允许 storage/backup/*.sql 与 images/**,并禁止可执行扩展名。
flowchart TD
Start(["开始"]) --> Act{"动作"}
Act --> |备份| Build["构建表清单"]
Build --> Dump["分卷导出 SQL"]
Dump --> Zip{"是否打包资源?"}
Zip --> |是| Pack["Zip::create(SQL + images)"]
Zip --> |否| Done1["完成"]
Pack --> Done1
Act --> |恢复| Unzip{"是否为 zip?"}
Unzip --> |是| Extract["Zip::extract(白名单)"]
Unzip --> |否| Exec["执行 SQL"]
Extract --> Exec
Exec --> NextVol{"是否还有分卷?"}
NextVol --> |是| Exec
NextVol --> |否| Done2["完成"]
Act --> |删除| Confirm{"已确认?"}
Confirm --> |否| Prompt["提示确认"]
Confirm --> |是| Del["删除主文件+分卷"]
Del --> Done3["完成"]
附件上传与存储
- 存储策略
- 默认磁盘 local,根目录 images/upload;可通过 FilesystemManager 按约定推导 images/{module}/ 或动态 build 任意相对路径。
- 上传策略集中配置:最大文件大小、允许扩展名、图片质量、缩略图目录等。
- 上传流程
- 前端/后台调用 attachment()->store/storeDraft,内部走 ChunkedUploadHandler 处理分片合并、缩略图、元数据入库。
- 支持草稿模式(draft),最终由业务提交时认领。
- 大文件与断点续传
- 分块上传:客户端分片,服务端按序号拼接后合并,最后清理临时片段。
- 断点续传:基于 blob_num/total_blob_num 与临时片段文件实现;失败后可重传缺失片段。
- 错误重试:分片写入失败会返回错误信息,前端可重试对应分片。
sequenceDiagram
participant FE as "前端/后台"
participant UC as "UserController"
participant AH as "ChunkedUploadHandler"
participant FS as "Storage/Disk"
participant DB as "file 表"
FE->>UC : 发起上传(可能分片)
UC->>AH : handle(disk, module, itemId, type, options, chunks)
AH->>FS : 写入分片 images/.../__N
AH->>AH : 当 last chunk 到达时合并文件
AH->>DB : 插入 file 记录(number, module, item_id, type, size, created_at...)
AH-->>FE : 返回结果(成功/错误)
配置文件与模板/静态资源备份
- 配置文件
- 系统配置:config/config.php(数据库、应用密钥、调试开关等)。
- 文件上传策略:config/file.php(默认磁盘、允许扩展名、大小限制、图片质量等)。
- 云服务 API:config/cloud.php(API 基地址、下载白名单)。
- 模板与静态资源
- 主题模板位于 theme// 与 _'/theme//,包含 .dwt、css、js、images 等。
- 静态资源与图片位于 images/*,模块专属目录如 product、video、download 等。
- 备份建议
- 将 config 目录、theme 目录、_'/theme 目录、images 目录纳入备份范围。
- 若使用云存储驱动扩展,需额外备份云端的对象存储桶与访问凭证。
依赖关系分析
- 控制器依赖服务:BackupController 依赖 BackupService。
- 服务依赖基础设施:BackupService 依赖数据库、Zip 工具、文件系统(images 目录)。
- 附件上传依赖存储抽象:UserController 通过 Attachment 服务与 Storage/FilesystemManager 交互,最终落到 LocalAdapter。
graph LR
BC["BackupController"] --> BS["BackupService"]
BS --> DB["数据库"]
BS --> ZIP["Zip 工具"]
BS --> IMG["images/*"]
UC["UserController"] --> ATT["AttachmentService"]
ATT --> CH["ChunkedUploadHandler"]
CH --> ST["Storage"]
ST --> FM["FilesystemManager"]
FM --> LA["LocalAdapter(images/*)"]
性能与优化
- 分卷导出
- 通过 vol_size 控制单卷大小,避免单次写入过大导致超时或内存不足。
- 使用 LIMIT 分页读取表数据,降低内存占用。
- 大文件上传
- 分块上传减少单次传输压力,支持失败分片重试与断点续传。
- 合并完成后清理临时片段,释放磁盘空间。
- 压缩与解压
- 打包 images 目录时按需启用,避免不必要的 IO。
- 解压时使用白名单与黑名单,防止恶意文件覆盖。
- 网络与并发
- 建议在服务器端开启合适的 PHP 执行时间与内存限制。
- 对超大库/大附件,建议使用离线工具或外部存储方案(如对象存储)配合定时同步。
故障排查指南
- 备份失败
- 检查 storage/backup 目录是否可写。
- 检查 SQL 分卷大小设置是否超过 upload_max_filesize。
- 查看错误消息中的 confirm_url 与 timeout,按提示继续下一步。
- 恢复失败
- 确认 zip 包内条目符合白名单(storage/backup/*.sql、images/**)。
- 检查 images 下被禁止的扩展名(php、phtml、phar、htaccess 等)。
- 多分卷恢复需按 volid 顺序执行。
- 上传失败
- 检查允许扩展名与单文件大小限制。
- 分片上传失败时根据返回的错误码重试对应分片。
- 草稿模式下确保在业务提交时正确认领。
结论
DouPHP 提供了完善的文件备份能力:数据库分卷导出、资源目录打包、安全解压与恢复;同时具备健壮的大文件分块上传与草稿机制。结合统一的文件系统抽象与配置管理,可轻松实现全量与增量备份策略,满足生产环境的可靠性与可恢复性要求。
附录:自动化与手动操作指南
手动备份操作
- 进入后台“备份”页面,选择要备份的表,设置文件名与分卷大小,点击“备份”。
- 如需同时备份附件资源,点击“备份并打包资源”,将生成 zip 包。
- 在“恢复备份”页可选择已有备份进行预览、下载或删除。
自动备份建议
- 定时任务
- 使用系统计划任务(如 crontab)定期调用备份接口,生成 SQL 与 zip 包。
- 将生成的备份包同步至远程存储(如对象存储),实现异地容灾。
- 增量备份策略
- 基于文件修改时间戳或哈希值识别变更文件:
- 扫描 images/、theme/、_'/theme/、config/ 等目录,记录上次快照(文件名、大小、mtime/hash)。
- 对比当前状态,仅备份新增或变更的文件。
- 将增量快照与全量快照结合,保留最近若干次全量与每日增量,平衡恢复成本与存储空间。
- 基于文件修改时间戳或哈希值识别变更文件:
- 大文件优化
- 分块上传与断点续传已在附件上传中实现;备份侧可对大文件采用分块压缩与并行传输。
- 对超大附件,考虑迁移至对象存储,并在备份中仅同步索引与元数据。
- 错误重试与幂等
- 备份任务应支持失败重试与幂等执行(相同参数多次执行不会产生重复包)。
- 记录每次备份的开始/结束时间、耗时、文件大小、错误日志。