Skip to content

FASUZO/PortraitVault

Repository files navigation

PortraitVault - 写真库浏览器

一个基于 FastAPI 的现代化写真库浏览系统,支持海报墙展示、缩略图预览、高清原图查看、视频播放和智能搜索。

功能特性

  • 📸 海报墙模式:优雅的文件夹封面展示,支持横屏竖屏自适应
  • 🖼️ 高清原图查看:灯箱模式预览,支持键盘导航和预加载
  • 🎬 视频支持:自动识别视频文件,提取首帧作为缩略图,支持在线播放
  • 🔍 极速搜索:文件名关键词搜索,支持多维度过滤(文件夹/图片/视频)
  • 收藏夹功能:一键收藏心仪的文件夹、图片和视频,专属收藏页面
  • ⚙️ 视图设置:自定义显示列数、缩略图大小等个性化设置
  • 🗂️ 多路径支持:同时管理多个照片库目录,跨盘符无缝浏览
  • 性能优化:智能缓存机制、异步文件读取、缩略图并发控制
  • 📱 响应式设计:完美适配桌面、平板和移动设备
  • 🔒 安全可靠:路径安全检查,防止越权访问,支持黑名单过滤

环境要求

  • Python: 3.10+
  • 核心依赖:
    • fastapi - Web 框架
    • uvicorn - ASGI 服务器
    • Pillow (PIL) - 图片处理,生成缩略图
    • aiofiles - 异步文件操作
    • python-dotenv - 环境变量管理
  • 可选依赖:
    • opencv-python - 视频缩略图生成(如果启用视频功能)
  • 前端框架:
    • Vue.js 3 (CDN)
    • Tailwind CSS (CDN)

安装所有依赖:

pip install -r requirements.txt

仅安装核心依赖(不使用视频功能):

pip install fastapi uvicorn Pillow aiofiles python-dotenv

快速开始

1. 安装依赖

pip install -r requirements.txt

2. 配置环境

Windows 开发环境

创建 .env 文件(可参考 .env.dev.windows):

# 支持单路径
PHOTOS_BASE_DIR=Z:\Pictures\R

# 支持多路径(用分号、逗号或空格分隔)
PHOTOS_BASE_DIR=Z:\Pictures\R;Y:\Pictures\Z

HOST=0.0.0.0
PORT=8000
DEBUG=true

# 可选:启用视频支持(默认启用)
ENABLE_VIDEO=true

# 可选:黑名单路径
BLACKLIST_PATHS=test文件夹,临时文件

Linux/Mac 开发环境

创建 .env 文件:

# 支持单路径
PHOTOS_BASE_DIR=/home/user/Pictures/R

# 支持多路径
PHOTOS_BASE_DIR=/home/user/Pictures/R,/mnt/nas/Photos

HOST=0.0.0.0
PORT=8000
DEBUG=true
ENABLE_VIDEO=true

Docker/NAS 部署环境

参考 .env.prod.dockerdocker-compose.yml 配置。

3. 运行应用

方式 1: 直接运行(开发)

python app/main.py

方式 2: 使用 uvicorn(生产)

uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload

4. 访问前端

打开浏览器访问:http://localhost:8000

使用指南

主要功能

1. 浏览照片库

  • 文件夹浏览:点击文件夹封面进入文件夹,支持面包屑导航
  • 图片查看:点击图片打开灯箱模式,支持键盘左右键切换(← →)
  • 视频播放:点击视频自动播放,支持播放控制
  • 返回上级:点击面包屑或按 ESC 键返回

2. 搜索功能

  • 快速搜索:点击侧边栏"功能面板",在搜索框输入关键词
  • 类型过滤:可选择只搜索文件夹、图片或视频
  • 搜索结果:点击结果自动跳转到对应位置
  • 搜索范围:自动搜索所有配置的照片库路径

3. 收藏夹管理

  • 添加收藏:点击缩略图右上角的 ⭐ 图标
  • 查看收藏:点击侧边栏"我的收藏"或访问 /favorites 页面
  • 删除收藏:在收藏页面点击删除按钮,或再次点击 ⭐ 图标取消收藏
  • 跳转定位:在收藏页面点击项目,自动跳转到原始位置

4. 视图设置

  • 显示列数:调整文件夹和图片的显示列数(1-10 列)
  • 缩略图大小:调整缩略图的最大高度(100-800px)
  • 设置保存:视图设置自动保存到浏览器本地存储

5. 多路径浏览

  • 当配置了多个 PHOTOS_BASE_DIR 时:
    • 系统会自动在所有路径中搜索和显示内容
    • 搜索结果会包含所有路径下的匹配项
    • 收藏夹可以跨路径收藏项目

键盘快捷键

  • ESC:关闭灯箱/视频播放器
  • / :在灯箱模式下切换上一张/下一张图片
  • 点击外部区域:关闭灯箱/侧边栏

界面特性

缩略图显示优化

  • 横屏竖屏自适应:自动适配不同比例的图片,无空白显示
  • 每行高度一致:同一行的所有缩略图高度一致,图片垂直居中
  • 完整显示:使用 object-contain 确保图片完整显示,不裁剪
  • 懒加载:只加载可见区域的缩略图,提升加载速度
  • 优先级加载:优先加载当前可见的缩略图,快速响应

性能特性

  • 智能缓存:自动缓存目录列表和缩略图,减少重复计算
  • 并发控制:限制同时生成的缩略图数量,避免系统过载
  • 中断机制:切换目录时自动中断之前的缩略图加载任务
  • 流式传输:大文件支持 Range 请求,支持断点续传

Docker 部署

1. 修改 docker-compose.yml

编辑 docker-compose.yml,修改 volumes 映射路径:

volumes:
  - /your/actual/photos/path:/photos:ro

例如(Synology NAS):

volumes:
  - /volume1/photo:/photos:ro

2. 构建并启动

docker-compose up -d --build

3. 访问

配置说明

环境变量配置(优先级最高)

变量名 说明 默认值 示例
PHOTOS_BASE_DIR 照片库根目录路径(支持多路径) 自动检测 Z:\Pictures\RZ:\Pictures\R;Y:\Pictures\Z
HOST 服务器绑定地址 0.0.0.0 0.0.0.0
PORT 服务器端口 8000 8000
DEBUG 调试模式 false true
ENABLE_VIDEO 启用视频支持 true true / false
THUMBNAIL_SIZE 缩略图尺寸(宽,高) 400,600 400,600
THUMBNAIL_QUALITY 缩略图质量 70 70
MAX_THUMBNAIL_CONCURRENT 最大并发缩略图生成数 3 3
ASYNC_FILE_READ 异步文件读取 true true / false
FILE_CHUNK_SIZE 文件读取块大小(字节) 8192 8192
BLACKLIST_PATHS 黑名单路径(多个用分号或逗号分隔) 人物A写真集\主题B,test

配置优先级

  1. 环境变量(最高优先级)
  2. .env 文件
  3. 默认配置

多路径配置

功能说明:

  • 支持同时配置多个照片库目录,跨盘符无缝浏览
  • 多个路径可以用分号(;)、逗号(,)或空格( )分隔
  • 系统会自动在所有配置的路径中搜索和显示内容

配置示例:

# Windows 多路径示例
PHOTOS_BASE_DIR=Z:\Pictures\R;Y:\Pictures\Z

# Linux/Mac 多路径示例
PHOTOS_BASE_DIR=/home/user/Pictures/R,/mnt/nas/Photos

# 带空格的多路径(使用引号包裹单个路径)
PHOTOS_BASE_DIR="Z:\Pictures\R Y:\Pictures\Z"

使用场景:

  • ✅ 照片库分布在多个硬盘或盘符
  • ✅ 需要同时浏览本地和网络存储
  • ✅ 统一管理多个不同的照片库

黑名单路径配置

功能说明:

  • 黑名单路径中的文件夹和文件将不会被扫描和显示
  • 支持相对路径(相对于 PHOTOS_BASE_DIR)和绝对路径
  • 多个路径可以用分号(;)或逗号(,)分隔
  • 路径匹配时包含所有子目录和文件(如果文件夹在黑名单中,其所有子内容也会被排除)

配置示例:

# 相对路径示例(相对于 PHOTOS_BASE_DIR)
BLACKLIST_PATHS=人物A写真集\主题B,人物B写真集\test文件夹

# 绝对路径示例
BLACKLIST_PATHS=Z:\Pictures\R\人物A写真集\主题B;Z:\Pictures\R\test

# 混合使用
BLACKLIST_PATHS=人物A写真集\主题B,/photos/test文件夹,绝对路径\文件夹

使用场景:

  • ✅ 排除测试文件夹或临时文件夹
  • ✅ 排除不想公开的私人文件夹
  • ✅ 排除正在整理或处理的文件夹
  • ✅ 排除包含大量文件的系统文件夹

注意事项:

  • 路径使用反斜杠(\)或正斜杠(/)都可以
  • Windows 路径可以使用反斜杠,Linux/Mac 使用正斜杠
  • 修改黑名单后需要重启应用才能生效

Windows 开发环境

在 Windows 上,如果未设置 PHOTOS_BASE_DIR,系统会:

  1. 尝试使用默认路径 Z:\Pictures\RY:\Pictures\Z
  2. 如果都不存在,使用项目目录下的 photos 文件夹

性能优化配置

缩略图生成性能:

  • MAX_THUMBNAIL_CONCURRENT:控制同时生成的缩略图数量(默认 3)
    • 增加此值可加快缩略图生成,但会消耗更多 CPU 和内存
    • 建议根据服务器性能调整(2-5 之间)

文件读取性能:

  • ASYNC_FILE_READ:启用异步文件读取(默认启用)
    • 对大文件和高并发场景有明显性能提升
  • FILE_CHUNK_SIZE:文件读取块大小(默认 8192 字节)
    • 对于大视频文件,可以适当增加此值(如 32768)

缓存配置:

  • 目录列表缓存:5 分钟(内存缓存,自动清理)
  • 缩略图缓存:24 小时(文件缓存,存储在 .cache/thumbnails
  • 收藏夹缓存:30 秒(内存缓存,减少文件IO)

Docker/NAS 部署

在 Docker 容器中:

  1. 自动检测容器环境(通过 /.dockerenv
  2. 默认使用 /photos 作为 BASE_DIR
  3. 通过 docker-compose.yml 的 volumes 映射实际路径

媒体文件组织与扫描

支持的图片格式

系统会自动识别以下格式的图片文件(不区分大小写):

  • .jpg / .jpeg
  • .png
  • .webp
  • .gif(包括动画 GIF,显示时会取第一帧作为缩略图)

支持的视频格式

系统支持以下视频格式(需要在配置中启用 ENABLE_VIDEO=true):

  • .mp4 / .m4v
  • .mov
  • .avi
  • .mkv
  • .webm
  • .flv
  • .wmv

视频功能说明:

  • 自动提取视频第一帧作为缩略图
  • 支持在线播放(使用浏览器原生播放器)
  • 视频缩略图生成需要安装 opencv-python(已在 requirements.txt 中包含)
  • 可以通过 ENABLE_VIDEO=false 禁用视频功能

目录结构建议

你可以灵活组织你的照片库目录结构,系统支持任意层级的文件夹嵌套:

Z:\Pictures\R\                    # BASE_DIR(根目录)
├── 人物A写真集\
│   └── 主题A
│   │    ├── 图片1.jpg
│   │    ├── 图片2.png
│   │    └── 子文件夹\
│   │          ├── 图片3.webp
│   │          ├── 视频1.MOV
│   │          └── 视频2.MP4
│   └── 主题B
│         ├── 图片1.jpg
│         ├── 图片2.png
│         └── 子文件夹\
│             └── 图片3.webp
├── 人物B写真集\
│   └── 图片4.jpg

关键要点:

  • ✅ 所有图片和文件夹必须放在 PHOTOS_BASE_DIR 目录下(或子目录中)
  • ✅ 支持任意深度的文件夹嵌套
  • ✅ 图片可以直接放在根目录,也可以放在任意子文件夹中
  • ✅ 文件夹会自动显示,点击可进入查看内容

文件命名规则

系统会自动处理:

  • ✅ 文件名支持中文、英文、数字和常用符号
  • ✅ 不区分大小写(.JPG.jpg 都会被识别)
  • ✅ 文件名中可以包含空格

会被跳过的内容:

  • ❌ 隐藏文件和文件夹(以 . 开头的,如 .DS_Store.hidden
  • ❌ 非支持格式的文件(如 .txt.pdf 等,除非是图片或视频格式)
  • ❌ 视频文件(如果 ENABLE_VIDEO=false 时会被跳过)
  • ❌ 系统没有访问权限的文件或文件夹
  • ❌ 黑名单路径中的文件夹和文件(通过 BLACKLIST_PATHS 配置)
  • ❌ 空文件夹或只包含不支持格式文件的文件夹

文件夹封面

系统会自动为每个文件夹生成封面图(优化版本):

  1. 智能查找策略(按优先级):

    • 策略 1:优先查找当前文件夹直接包含的图片或视频
    • 策略 2:如果当前文件夹没有,查找直接子文件夹中的第一张图片/视频
    • 策略 3:如果以上都没有,递归查找深层文件夹中的第一张图片/视频
    • 按照文件名的字母顺序查找
    • 支持图片和视频作为封面(仅在启用视频功能时包含视频)
  2. 封面缓存:

    • 封面查找结果会被缓存,避免重复计算
    • 缓存大小限制为 1000 个条目,自动清理
  3. 建议:

    • 在文件夹的根目录放置一张代表性图片作为封面(命名靠前,如 封面.jpg01-封面.jpg
    • 或者在子文件夹的第一层放置图片,系统会自动查找
    • 文件名可以使用数字前缀来控制封面选择顺序
    • 如果文件夹只包含视频且启用视频功能,会自动使用视频第一帧作为封面

扫描行为说明

  • 实时扫描: 每次浏览目录时都会实时扫描文件系统,显示最新内容
  • 缓存机制:
    • 目录列表缓存 5 分钟(内存缓存)
    • 缩略图缓存 24 小时(文件缓存)
    • 封面图片缓存(避免重复计算)
    • 收藏夹数据缓存 30 秒(减少文件IO)
  • 排序规则: 文件夹和媒体文件按名称字母顺序排列
  • 递归搜索: 文件夹封面会智能搜索:优先当前目录 → 直接子目录 → 深层递归
  • 性能优化:
    • 异步文件读取,支持大文件流式传输
    • 缩略图生成并发控制(默认最多 3 个并发)
    • 智能缓存清理,自动管理内存和磁盘空间

最佳实践

  1. 保持目录整洁:

    推荐结构:
    Z:\Pictures\R\
    ├── 2024年\
    │   ├── 写真集1\
    │   │   ├── 封面.jpg  # 命名靠前,优先作为封面
    │   │   ├── 001.jpg
    │   │   └── 002.jpg
    │   └── 写真集2\
    └── 2025年\
        └── 写真集3\
    
  2. 命名规范:

    • 使用有意义的文件夹名称(如主题、日期等)
    • 图片文件可以使用编号前缀(001.jpg, 002.jpg)保证顺序
    • 封面图片可以使用 封面.jpg01-封面.jpg 等名称,确保优先显示
  3. 避免的问题:

    • 不要将图片放在隐藏文件夹中(以 . 开头)
    • 不要在文件夹名称中使用特殊符号(如 <, >, :, ", |, ?, *
    • 确保图片文件完整,避免损坏的图片文件
  4. 性能优化建议:

    • 单个文件夹内不建议放置过多文件(建议 < 1000 个)
    • 使用合理的文件夹层级(建议不超过 5 层)
    • 定期清理 .cache/thumbnails 目录释放磁盘空间(可选)
    • 使用黑名单功能排除不需要扫描的目录
  5. 多路径管理:

    • 将不同类型的照片库分开存储(如:写真库、视频库)
    • 使用有意义的盘符或路径名称便于识别
    • 注意路径访问权限,确保所有路径都可读
  6. 收藏夹使用:

    • 收藏常用的文件夹,快速访问
    • 收藏精美的图片或视频,便于回顾
    • 定期整理收藏夹,保持整洁

目录结构

PortraitVault/
├── app/
│   ├── main.py          # 主应用文件(API 路由和业务逻辑)
│   ├── config.py        # 配置管理模块(支持多路径、黑名单等)
│   ├── cache.py         # 缓存管理模块(内存缓存和文件缓存)
│   └── static/
│       ├── index.html   # 主页面(浏览、搜索、视图设置)
│       ├── favorites.html  # 收藏夹页面
│       ├── favicon.ico  # 网站图标
│       └── 404.png      # 占位符图片
├── .cache/
│   └── thumbnails/      # 缩略图缓存目录(自动生成)
├── favorites.json       # 收藏夹数据文件(自动生成)
├── docker-compose.yml   # Docker Compose 配置
├── Dockerfile          # Docker 镜像构建文件
├── requirements.txt    # Python 依赖
├── .env.example        # 环境变量配置示例
├── env.dev.windows     # Windows 开发环境示例
├── env.prod.docker     # Docker 生产环境示例
└── README.md          # 本文件

API 接口

前端页面

  • GET / - 主页面(照片库浏览)
  • GET /favorites - 收藏夹页面
  • GET /favicon.ico - 网站图标

核心 API

  • GET /api/browse?path= - 浏览目录内容(支持多路径)
  • GET /api/thumbnail?path= - 获取缩略图(图片/视频/文件夹封面)
  • GET /api/raw?path= - 获取高清原图或视频(支持 Range 请求)

搜索与收藏

  • GET /api/search?keyword=...&file_type=...&limit=... - 搜索文件(支持文件名关键词、类型过滤)
  • GET /api/favorites - 获取所有收藏项
  • POST /api/favorites - 添加收藏项(Body: {path, name, type}
  • DELETE /api/favorites?path=... - 删除收藏项

搜索功能说明:

  • 支持文件名关键词搜索(不区分大小写)
  • 支持类型过滤:folder(文件夹)、image(图片)、video(视频)
  • 支持结果数量限制(默认 100,最大 1000)
  • 搜索范围包括所有配置的 PHOTOS_BASE_DIR
  • 搜索结果实时返回,毫秒级响应

收藏夹功能说明:

  • 支持收藏文件夹、图片和视频
  • 收藏数据持久化存储在 favorites.json
  • 提供专门的收藏页面进行管理
  • 支持一键跳转到原始位置

安全说明

  • 路径安全检查:防止访问 BASE_DIR 以外的目录,防止路径遍历攻击
  • 只读挂载:Docker 部署建议使用 :ro(只读)挂载,保护原文件不被修改
  • 隐藏文件过滤:自动跳过以 . 开头的隐藏文件和文件夹
  • 黑名单机制:支持配置黑名单路径,排除不需要访问的目录
  • 多路径验证:所有路径都经过安全验证,确保在允许范围内
  • 输入验证:所有 API 输入都经过验证和清理,防止注入攻击

故障排查

问题:提示 "BASE_DIR 不存在"

解决方案:

  1. 检查 .env 文件中的 PHOTOS_BASE_DIR 路径是否正确
  2. 在 Windows 上,确保使用正确的路径格式(如 Z:\Pictures\R
  3. 在 Linux 上,确保路径存在且有访问权限

问题:Docker 容器中无法访问文件

解决方案:

  1. 检查 docker-compose.yml 中的 volumes 映射是否正确
  2. 确保 NAS 上的路径存在且容器有访问权限
  3. 检查 Docker 的共享文件夹设置

问题:缩略图生成失败

解决方案:

  1. 确保 Pillow 已正确安装:pip install Pillow
  2. 检查图片文件是否损坏
  3. 查看服务器日志获取详细错误信息

问题:图片无法显示或被扫描到

可能原因及解决方案:

  1. 图片格式不支持

    • ✅ 确保图片格式为 .jpg, .jpeg, .png, .webp, .gif 之一
    • ❌ 其他格式(如 .bmp, .tiff, .ico 等)不会被扫描
    • 💡 注意:动画 GIF 在缩略图中会显示第一帧,点击查看原图可以看到完整动画效果
  2. 文件在隐藏文件夹中

    • 检查文件夹名称是否以 . 开头(如 .hidden
    • 隐藏文件和文件夹会被自动跳过
  3. 文件路径超出 BASE_DIR

    • 确保所有图片都在 PHOTOS_BASE_DIR 目录下
    • 检查 .env 文件中的路径配置是否正确
  4. 权限问题

    • Windows:确保运行 Python 的用户有读取照片目录的权限
    • Linux/Mac:检查文件权限(chmod)和所有者
  5. 文件损坏

    • 尝试用其他软件打开图片,确认文件完整
    • 损坏的图片可能无法生成缩略图
  6. 缓存问题

    • 如果修改了文件但界面没更新,等待 5 分钟后自动刷新
    • 或清除浏览器缓存后重新加载

问题:文件夹封面无法显示

解决方案:

  1. 确保文件夹内至少有一张支持的图片格式(或视频文件,如果启用视频功能)
  2. 检查子文件夹中是否有图片(系统会递归搜索)
  3. 如果文件夹为空,会显示默认占位符(这是正常现象)
  4. 等待缓存过期(24小时)后,封面会自动更新

问题:视频无法播放或缩略图生成失败

解决方案:

  1. 确保已安装 opencv-pythonpip install opencv-python
  2. 检查配置中 ENABLE_VIDEO=true(默认已启用)
  3. 确认视频文件格式在支持列表中
  4. 检查视频文件是否损坏(尝试用其他播放器打开)
  5. 视频缩略图生成可能需要较长时间,请耐心等待

问题:搜索功能无法使用

解决方案:

  1. 确保搜索关键词不为空
  2. 检查是否选择了正确的文件类型过滤
  3. 搜索结果限制在 1000 条以内,如果结果太多,尝试更具体的关键词
  4. 搜索会在所有配置的 PHOTOS_BASE_DIR 中进行

问题:多路径配置不生效

解决方案:

  1. 检查路径分隔符是否正确(支持 ;, 或空格)
  2. 确保所有路径都存在且可访问
  3. Windows 路径可以使用反斜杠或正斜杠
  4. 修改配置后需要重启应用
  5. 查看启动日志确认所有路径都已加载

问题:收藏夹数据丢失

解决方案:

  1. 检查 favorites.json 文件是否存在且可读写
  2. 确保应用有写入权限
  3. 收藏数据存储在项目根目录下的 favorites.json
  4. 可以手动备份该文件防止数据丢失

更新日志

最新版本特性

核心功能增强

  • 多路径支持:支持同时配置多个照片库目录,跨盘符无缝浏览
  • 视频支持:自动识别视频文件,提取首帧作为缩略图,支持在线播放
  • 极速搜索:文件名关键词搜索,支持多维度过滤,毫秒级响应
  • 收藏夹功能:一键收藏,专属收藏页面,支持快速访问

性能优化

  • 智能缓存:多层次缓存机制,自动清理过期缓存
  • 异步处理:异步文件读取,支持大文件流式传输
  • 并发控制:缩略图生成并发控制,避免系统过载
  • 懒加载:缩略图懒加载,优先加载可见区域

用户体验优化

  • 横屏竖屏自适应:自动适配不同比例的图片,无空白显示
  • 视图设置:自定义显示列数和缩略图大小
  • 响应式设计:完美适配各种设备
  • 键盘快捷键:支持键盘导航,提升操作效率

代码质量提升

  • 代码精简:提取通用函数,减少重复代码
  • 性能优化:优化文件扫描和搜索算法
  • 稳定性增强:统一错误处理,原子性文件操作
  • 可维护性:优化代码结构,提升可读性

技术架构

  • 后端框架:FastAPI(异步、高性能)
  • 前端框架:Vue.js 3(组合式 API)
  • 样式框架:Tailwind CSS(响应式、现代化)
  • 图片处理:Pillow(缩略图生成)
  • 视频处理:OpenCV(视频缩略图提取)
  • 缓存策略:内存缓存 + 文件缓存
  • 部署方式:Docker 容器化部署

许可证

MIT License

贡献

欢迎提交 Issue 和 Pull Request!

致谢

感谢所有使用和支持 PortraitVault 的用户!

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published