# picbed **Repository Path**: xunjinlu/picbed ## Basic Information - **Project Name**: picbed - **Description**: PicBed - 轻量级多类型文件管理系统 | 支持图片/视频/音频/文档上传管理、在线预览、同源安全防护、子目录部署、响应式界面 - **Primary Language**: PHP - **License**: Not specified - **Default Branch**: master - **Homepage**: https://gitee.com/xunjinlu/picbed - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-01-13 - **Last Updated**: 2026-07-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README

PicBed - 轻量级多类型文件管理系统

支持图片、视频、音频、文档、文本、代码等多种文件类型的上传与在线预览

## 功能特性 ### 文件管理 - **全类型支持** - 图片、视频、音频、文档、文本、代码、压缩包等 - **在线预览** - 图片直接查看,视频/音频在线播放,文本/代码在线阅读,PDF 在线预览 - **文件分类** - 自动识别文件类型,彩色标签标识(图片/视频/音频/文档/文本/代码/压缩包) - **批量上传** - 支持拖拽上传、多文件同时上传 - **文件替换** - 保持链接不变,替换文件内容 - **文件删除** - 管理员可删除文件 ### 链接格式 上传后支持 7 种链接格式输出: - **URL** - 直接链接 - **Markdown** - `![alt](url)` - **HTML** - `` 标签 - **BBCode** - `[img]url[/img]` - **UBB** - `[IMG]url[/IMG]` - **CSS** - `background-image` - **JSON** - JSON 格式 ### 命名规则 支持 7 种文件命名方式: - 自然序号递增(从 1 开始,自动增加位数) - 时间戳(YmdHis) - 日期+序号 - UUID - MD5 随机 - 短随机字符(8位) - 前缀+日期 ### 系统功能 - **JSON 配置** - 所有配置通过 Web 页面管理,存储在 `data/config.json` - **自定义上传目录** - 可在设置中自定义上传文件夹路径,支持多层子目录,默认 `img/` - **多文件夹管理** - 支持多个上传目录共存,文件库可按目录筛选,历史目录文件不丢失 - **手动扫描** - 保存设置时自动扫描所有历史目录补全数据,新版部署不自动扫描 - **同源安全校验** - 所有写操作检查 Origin/Referer 同源,防止外部抓包直接调用 API - **本地数据库** - `data/db.json` 存储文件元信息(名称、大小、时间) - **自动迁移** - 首次使用自动扫描已有文件导入数据库 - **密码安全** - password_hash 加密存储 - **会话管理** - 可配置超时时间,支持记住登录 - **游客上传** - 可配置是否需要登录才能上传 - **页脚配置** - 支持版权信息、ICP 备案号、公安备案号 - **累计统计** - 显示当前文件数量和占用空间 - **响应式设计** - 完美适配手机和电脑 ### 文件类型快捷配置 设置页面提供文件类型预设按钮: - 仅图片 - 图片+视频+音频 - 文档 - 代码 - 全部类型 ## 安装部署 ### 环境要求 - PHP 7.4 / 8.0 / 8.2 - Web 服务器(Nginx / Apache) - 目录写权限 ### 安装步骤 1. 下载源码并上传到服务器 2. 解压到 Web 目录 3. 确保 `data/` 目录有写权限 4. 确保 `img/` 目录有写权限 5. 访问 `index.php` 开始使用 ### 目录权限 ```bash chmod 755 /path/to/picbed chmod 755 /path/to/picbed/data chmod 755 /path/to/picbed/img ``` ### Nginx 配置示例 ```nginx server { listen 80; server_name your-domain.com; root /path/to/picbed; index index.php; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { fastcgi_pass unix:/tmp/php-cgi.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } location ~* ^/(data)/ { deny all; } } ``` ## 目录结构 ``` picbed/ ├── index.php # 上传页面 ├── gallery.php # 文件库页面 ├── settings.php # 设置页面 ├── api.php # API 接口(全部合并) ├── README.md # 说明文档 ├── assets/ │ ├── css/ │ │ ├── common.css # 公共样式 │ │ ├── index.css # 上传页面样式 │ │ ├── gallery.css # 文件库样式 │ │ └── settings.css # 设置页面样式 │ └── js/ │ ├── common.js # 公共脚本 │ ├── index.js # 上传页面脚本 │ ├── gallery.js # 文件库脚本 │ └── settings.js # 设置页面脚本 ├── data/ │ ├── .htaccess # 禁止直接访问 │ ├── config.json # 站点配置 │ ├── db.json # 文件数据库 │ └── stats.json # 统计数据(累计上传数、占用空间、计数器) └── img/ # 上传文件存储目录 ``` ## API 接口 ### 认证相关 | 接口 | 方法 | 说明 | |------|------|------| | `?act=auth_status` | GET | 获取认证状态 | | `?act=login` | POST | 登录(JSON: `{password}`) | | `?act=logout` | POST | 登出 | | `?act=changepwd` | POST | 修改密码(JSON: `{old_password, new_password}`) | ### 文件操作 | 接口 | 方法 | 说明 | |------|------|------| | `?act=upload` | POST | 上传文件(FormData: `image[]`) | | `?act=list` | GET | 文件列表(参数: `page`, `sort`, `per_page`) | | `?act=info` | GET | 文件信息(参数: `filename`) | | `?act=filetype` | GET | 文件类型分类(参数: `filename`) | | `?act=delete` | POST | 删除文件(JSON: `{filename}`) | | `?act=replace` | POST | 替换文件(FormData: `image`, `replace_filename`) | ### 配置相关 | 接口 | 方法 | 说明 | |------|------|------| | `?act=config` | GET | 获取公开配置 | | `?act=config_all` | GET | 获取完整配置(需登录) | | `?act=config_save` | POST | 保存配置(需登录) | | `?act=stats` | GET | 获取统计数据 | ### 文件类型分类 系统自动将文件分为以下类别: | 分类 | 扩展名 | 预览方式 | |------|--------|----------| | 图片 | jpg, png, gif, webp, svg, bmp, tiff | 直接预览 | | 视频 | mp4, avi, mov, mkv, webm | 在线播放 | | 音频 | mp3, wav, ogg, flac, aac | 在线播放 | | 文档 | pdf, doc, docx, xls, xlsx, ppt, pptx | PDF 在线预览,其他下载 | | 文本 | txt, md, log, csv, ini, rtf | 在线查看 | | 代码 | json, xml, html, css, js, py, sql, sh 等 | 在线查看(等宽字体) | | 压缩包 | zip, rar, 7z, tar, gz | 仅上传,不支持预览 | ## 配置说明 所有配置存储在 `data/config.json`,可通过设置页面修改: | 配置项 | 默认值 | 说明 | |--------|--------|------| | site_name | PicBed | 站点名称 | | enable_auth | true | 启用鉴权 | | upload_auth | true | 上传需要登录 | | admin_password | admin123 | 管理员密码 | | session_timeout | 7200 | 会话超时(秒) | | remember_login | true | 记住登录 | | allowed_types | jpg,png,gif,... | 允许的文件类型 | | naming_rule | sequential | 命名规则 | | naming_prefix | | 命名前缀 | | max_file_size_mb | 50 | 最大文件大小(MB) | | upload_dir | img | 当前上传目录(支持多层子目录,如 uploads/images) | | upload_dirs | ["img"] | 历史上传目录列表(自动维护) | | images_per_page | 20 | 每页文件数 | | copyright | | 版权信息 | | icp | | ICP 备案号 | | police_icp | | 公安备案号 | ## 更新日志 ### v3.38.1 (2026-06-20) - 完善 counter 同步机制,确保删除后编号永不回退 - `picbed_getNextCounter()` 改为始终取 `max(counter, max_seq+1)`,不再有条件判断 - `picbed_rebuild_stats()` 增加 counter 同步:取 `max(已有counter, db最大编号+1)` - `picbed_migrate_stats()` 从旧文件迁移时也确保 `counter >= db最大编号+1` - 部署/升级时自动检索 db.json 更新 counter,无需手动操作 - 删除文件后编号永久废弃,新文件接着最大编号继续递增 ### v3.38.0 (2026-06-20) - 修复递增命名填补已删除编号空缺的问题 - 新增 `picbed_getMaxSeqFromDb()` 从 db.json 提取最大顺序编号 - `picbed_getNextCounter()` 确保 counter 不小于 db 中最大编号+1 - 删除文件后上传新文件,接着最大编号继续递增,而非填补空缺 - `picbed_migrate_stats()` 初始化 counter 改为最大编号+1(原为 `count($db)`) - 修复 `stats.json` 丢失后 counter 从0开始导致填补空缺的问题 ### v3.37.3 (2026-06-20) - 修复子目录部署扫描双重路径问题(彻底修复) - 扫描逻辑重构:只扫描当前 `upload_dir`,不再扫描 `upload_dirs` 中的历史目录 - 之前扫描 `upload_dirs` 中所有目录(包括 `img` 三级目录),导致文件被记录为 `dir='img'` - URL 生成 `baseUrl + 'img/' + filename` 出现双重路径(如 `/img/img/filename`) - 现在只扫描当前 `upload_dir`,所有记录的 `dir` 统一为当前 `upload_dir` 值 - `picbed_db_repair()` 同步重构:只检查当前 `upload_dir`,统一 `dir` 字段 - 不在当前 `upload_dir` 中的文件记录将被自动清理 - 修复 PicBed 部署在 `/img/` 且 `upload_dir='.'` 时 URL 出现 `/img/img/` 的问题 ### v3.37.2 (2026-06-20) - 修复子目录部署时扫描生成双重路径名 - `picbed_rebuild_db_from_all_dirs()` 保留旧记录时增加文件位置验证 - 旧记录的文件不在原 `dir` 时,自动尝试当前 `upload_dir`,找到则更新 `dir` - 文件不存在于任何目录时丢弃记录,避免产生无效 URL - `picbed_db_repair()` 增加根目录兜底查找,修正错误的 `dir` 字段 - 修复 PicBed 部署在子目录(如 `/img/`)且 `upload_dir='.'` 时 URL 出现双重 `img` 的问题 ### v3.37.1 (2026-06-20) - 修复根目录扫描系统文件 + 计数不一致 - 新增 `picbed_isSystemFile()` 函数,扫描时排除系统文件 - 所有 `.php` 文件、`.htaccess`、`README.md` 等不再被扫描记录 - 根目录额外排除 `LICENSE`、`CHANGELOG.md`、`Dockerfile` 等项目文件 - `dirs` API 计数改为按 `allowed_types` 过滤,与文件库显示一致 - `picbed_db_repair()` 自动清理已存在的系统文件记录 ### v3.37.0 (2026-06-20) - 安全机制完全重构 - 移除 CSRF Token 机制(导致 session 竞态、登录失败、保存失败) - 改用 Origin/Referer 同源检查,防止外部抓包直接调用 API - 所有写操作(upload/delete/replace/config_save/changepwd)增加同源校验 - 同源检查兼容 HTTP/HTTPS、不同端口、反向代理场景 - 移除 `getPublicConfig` 中的 `csrf_token` 字段 - 前端移除所有 CSRF Token 相关代码(`csrfToken`/`ensureCsrfToken`) - 恢复所有写请求为原始格式,不再携带 Token ### v3.36.3 (2026-06-20) - 修复 CSRF Token 异步竞态导致验证失败 - `checkAuth()` 中获取 CSRF Token 的 fetch 是异步的,callback 不等它完成 - 新增 `ensureCsrfToken()` 等待机制,确保 Token 获取后再发送写请求 - 所有写操作(upload/save/delete/replace/changepwd)使用 `ensureCsrfToken` 包裹 ### v3.36.2 (2026-06-20) - 修复 CSRF Token 验证后销毁导致后续操作失败 - 移除 `picbed_verifyCsrfToken()` 中验证后销毁 token 的逻辑 - Token 在 session 生命周期内持续有效,支持多次操作 - 修复设置页面保存、文件删除等操作提示"安全验证失败"的问题 ### v3.36.1 (2026-06-20) - 修复 CSRF Token 多次调用覆盖导致验证失败 - Token 改为复用机制:session 中已有 token 则复用,不再每次覆盖 ### v3.36.0 (2026-06-20) - 上传安全机制 + 根目录支持修复 - 新增 CSRF Token 防护,防止抓包直接调用 API 上传 - 所有写操作(upload/replace/delete/config_save/changepwd)需携带 Token - Token 通过 session 生成,页面加载时从 `api.php?act=config` 获取 - Token 验证后自动销毁,防止重放攻击 - 修复根目录(`.`)配置:URL 生成去除 `./` 前缀 - 新增 `picbed_getFilePath()` 辅助函数统一处理根目录路径 ### v3.35.0 (2026-06-20) - 多文件夹支持 + 扫描机制重构 - `db.json` 每条记录新增 `dir` 字段,记录文件所在目录 - `config.json` 新增 `upload_dirs` 数组,记录所有使用过的上传目录 - 扫描机制改为手动触发(保存设置时扫描所有历史目录) - 新版部署后不再自动扫描,改为用户保存设置时才扫描 - `list` API 新增 `dir` 参数,支持按目录过滤文件 - 新增 `dirs` API,返回所有已知的上传目录列表及各目录文件数 - 删除/替换操作优先使用记录中的 `dir` 字段定位文件 - 文件库页面新增文件夹选择器,支持按目录筛选 - 不选择目录时显示所有目录的文件(兼容历史文件) - 编号计数器全局递增,跨目录继承编号 - `getPublicConfig` API 返回 `upload_dirs` 供前端使用 ### v3.34.0 (2026-06-20) - 新增自定义上传文件夹功能 - 设置页面"上传设置"中新增"上传目录"配置项 - 支持自定义上传文件夹路径,如 `uploads/images/2026` - 支持多层子目录,支持根目录(`.`)直接上传到站点根 - 不配置时默认使用 `img` 文件夹 - 路径安全校验:禁止 `../` 路径穿越,禁止绝对路径 - 文件库灯箱和卡片缩略图路径改为动态获取 `upload_dir` - `getPublicConfig` API 返回 `upload_dir` 供前端使用 ### v3.33.0 (2026-06-19) - 优化卡片堆叠密度和溢出问题 - 卡片尺寸从 80px 缩小到 72px,重叠间距从 -24px 缩小到 -20px - 手机端卡片 56px,重叠间距 -14px - 手机端最多显示 5 张卡片,桌面端最多 8 张,超出显示 `+N` - 旋转角度收窄(-8° 到 +13°),更紧凑美观 - `+N` 卡片使用虚线边框区分 - 选择框和上传结果区域统一优化 ### v3.32.0 (2026-06-19) - 恢复灯箱抽屉为固定高度 ### v3.31.0 (2026-06-19) - 修复覆盖安装后 stats.json 为空不自动重建的问题 ### v3.30.0 (2026-06-19) - 修复覆盖安装后 db.json 为空不自动重建的问题 ### v3.29.0 (2026-06-19) - 彻底恢复 v3.25 的文件库 UI 样式 ### v3.28.0 (2026-06-19) - 修复文件库页面 UI 完全崩溃的问题 ### v3.27.0 (2026-06-19) - 修复文件库页面报错(灯箱 HTML/JS/CSS 结构不匹配) ### v3.26.0 (2026-06-19) - 灯箱预览区域真正自适应 ### v3.25.0 (2026-06-19) - 页脚链接支持自定义 ### v3.24.0 (2026-06-19) - 修复顺序命名计数器不递增的问题 ### v3.23.0 (2026-06-19) - 上传页面显示已选文件总大小 ### v3.22.0 (2026-06-19) - 版本升级检测 + 自动修复统计数据 ### v3.21.0 (2026-06-19) - 修复上传结果区域文档预览触发下载的问题 ### v3.20.0 (2026-06-19) - 上传动效 + 逐个上传燃尽效果 ### v3.18.0 (2026-06-19) - 上传页面全面优化 ### v3.17.3 (2026-06-19) - 预览区域高度自适应,超出弹窗支持滚动 ### v3.17.2 (2026-06-19) - 修复视频预览控制条被挤出弹窗的问题 ### v3.17.1 (2026-06-19) - 修复 PDF 在线预览加载失败的问题 - 禁用 pdf.js Web Worker,改用主线程解析 PDF - 避免 worker 文件路径加载失败或 CORS 跨域问题 - 错误提示显示具体错误信息,便于排查问题 ### v3.17.0 (2026-06-19) - 卡片缩略图增强 - 视频卡片自动加载视频首帧(0.5秒处)作为封面缩略图 - 视频封面右下角显示播放按钮(鼠标悬停时显示) - 音频卡片显示渐变色封面(紫蓝粉渐变 + 音乐图标) - 图片卡片保持原有缩略图显示 - 动态照片兼容 - 各手机厂商的动态照片(Motion Photo,后缀为 .jpg)正常显示静态图片部分 - 浏览器 `` 标签自动渲染 JPEG 中的静态图片 ### v3.16.0 (2026-06-19) - JS 库本地化部署 - marked.js、pdf.js(含 worker)、mammoth.js 下载到 `assets/libs/` 目录 - 不再依赖外部 CDN,避免国外站点访问慢或关闭导致预览失败 - 灯箱预览区域动态高度 - 预览区域改为 `flex:1` 自适应,不再固定 `max-height` - 灯箱总高度增大到 85vh(电脑)/ 90vh(手机/大屏) - 文档/文本/PDF/视频等文件预览区域自动占满剩余空间 - MD 文档、PDF、Word 等文件预览空间大幅增加 ### v3.15.0 (2026-06-19) - PDF 文件在线预览(使用 pdf.js 渲染到 Canvas) - 解决 iframe 直接嵌入 PDF 触发浏览器下载的问题 - 支持多页 PDF 逐页渲染,自动适配容器宽度 - 加载失败时显示友好错误提示 - Word (.docx) 文件在线预览(使用 mammoth.js 转换为 HTML) - 支持标题、段落、表格、图片等元素渲染 - 加载/解析失败时显示友好错误提示 ### v3.14.0 (2026-06-19) - MD 文件渲染为网页格式在线预览 - 引入 marked.js 库,MD 文件在灯箱弹窗中渲染为格式化网页 - 预览区域右上角添加「渲染/源码」切换按钮 - MD 文件默认显示渲染视图,其他文本/代码默认显示源码 - 渲染视图支持标题、列表、代码块、表格、引用、链接、图片等完整 Markdown 语法 - 渲染视图样式美观,与系统主题一致 - PDF 文件保持 iframe 在线预览 ### v3.13.2 (2026-06-19) - 修复 db.json 中缺少上传时间字段的问题 - 新增 `picbed_db_repair()` 自动修复函数 - 每次页面加载时自动检测并补充缺失的 time/size/path/remark 字段 - 从实际文件获取 filemtime 作为上传时间 ### v3.13.1 (2026-06-19) - 修复设置页面未登录时加载动画一直显示不消失的问题 ### v3.13.0 (2026-06-19) - 页面标题统一移到顶部导航栏 - 所有页面去除主体区域的页面标题(如"文件库"、"上传文件"、"系统设置") - 顶部栏品牌名改为「站点名 - 页面名」格式(如 `PicBed - 文件库`) - 文件库工具栏布局重构 - 搜索框固定在左侧,排序/布局/管理按钮固定在右侧 - 电脑端:搜索框和按钮在同一行,两端对齐 - 手机端:搜索框独占第一行,按钮在第二行右对齐 - 统计信息(共 X 个文件)移至工具栏上方单独一行 ### v3.12.0 (2026-06-19) - 文件库页面新增搜索功能:支持按文件名和备注关键词搜索 - 搜索框带 350ms 防抖,避免频繁请求 - 搜索结果自动重置到第一页 - 支持清除搜索按钮一键清空 - 上传页面自动提取文件名作为备注 - 仅对非图片文件生效(文档/音频/文本/视频/代码等) - 单文件选择时自动将文件名(去掉扩展名)填入备注框 - 图片文件不自动填入备注 - 备注框已有内容时不覆盖 ### v3.11.0 (2026-06-19) - 文件库卡片标签显示具体扩展名(如 "文档 DOCX"、"视频 MP4"、"音频 MP3") - 页脚重构:去除底部栏,改为 flex 布局 - 手机端(<768px):三行显示(版权 / ICP / 公安备案各一行) - 电脑端:一行显示,自动居中排列 - 版权信息年份自动跟随当前时间(`date('Y')`) - 版权信息链接跳转到 copyright.gov.cn - 设置页面版权输入提示优化:只需输入公司名/版权主体 ### v3.10.0 (2026-06-18) - 全面美化 UI 动效 - 音频播放器:圆形图标脉冲动画 + 音频波形条动画 + 渐变背景 - 视频播放器:圆角美化 + 投影效果 + 控制栏渐变背景 - 上传进度条:渐变填充 + 光泽流动动画 - 卡片入场动画(淡入+上浮+缩放弹性效果) - 卡片悬停:增强阴影 + 边框高亮 + 图片缩放 - 下拉菜单:弹性弹出动画 - Toast 通知:弹性滑入动画 - 模态框:弹性缩放动画 - 关闭按钮:悬停旋转 90 度效果 - 类型标签:滑入动画 - 分页按钮:悬停上浮 + 选中发光 - 空状态图标:上下浮动动画 - 新增骨架屏 shimmer 动画基础样式 ### v3.9.0 (2026-06-18) - 合并 counter.txt 和 total.txt 为 stats.json 统一存储 - 新增 total_size 字段记录占用空间总计 - stats API 直接读取 stats.json,不再遍历 db.json 计算空间 - 上传/删除/替换自动同步占用空间统计 - 自动从旧版 counter.txt/total.txt 迁移到 stats.json ### v3.8.0 (2026-06-18) - 上传文件支持自定义备注(remark 字段) - 文件库卡片显示备注标签 - 灯箱弹窗显示文件备注 - info API 返回 remark 字段 - 上传页面增加备注输入框 - 备注存储在 data/db.json 中 ### v3.7.3 (2026-06-18) - 修复 settings.php 文件缺少 `