Skip to content
clockclock1Public

About

映匣 PixVault 是面向个人与团队的自托管图床与图库系统。支持图库分类管理、公开/私有分组、外链直链引用,以及完整的 REST API(上传、分类、随机取图等)。Web 控制台管理内容与密钥,图片与数据本地存储,无需依赖第三方云存储。

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

映匣 PixVault

自托管图床与图库:映匣(中文)/ PixVault(英文)。

面向个人与团队:上传、分类、外链分享、API Key 对接;支持公开分类随机取图。图片与元数据本地存储,无需依赖第三方云存储。

仓库:github.com/clockclock1/PixVault
镜像:ghcr.io/clockclock1/pixvault
许可证:Apache-2.0


功能概览

能力 说明
图库 Gallery 分类管理、磁盘文件夹同步、排序/筛选、缩略图与渐进式 JPEG
公开分类 分类可设为公开,通过 API 随机取一张图
外链直链 /s/{id} 返回渐进式 JPEG,适合 Markdown / <img>
API Key 外部程序用 pv_ 密钥调用上传与图库接口
简易图床 轻量 /api/upload → /i/{id} 原图外链
Web 控制台 登录、图库编辑、Key 管理、内置 API 文档
单进程部署 前端可嵌入二进制,一个可执行文件即可运行

技术架构

┌─────────────────┐     Cookie / API Key      ┌──────────────────────────┐
│  React Web UI   │ ◄───────────────────────► │  Axum (Rust) HTTP 服务   │
│  Vite + TS      │                           │  默认 :8765              │
└────────┬────────┘                           └────────────┬─────────────┘
         │ 开发态代理 /api /i /g /s                         │
         ▼                                                 ▼
   uniapp-android                                   SQLite + 本地磁盘
   (可选安卓客户端)                                  data/gallery、data/app.db

技术栈

层级 技术 作用
后端 Rust + Axum 0.8 异步 HTTP、multipart 上传、CORS、路由
存储 SQLite(rusqlite,bundled) 用户、会话、分类、图片元数据、API Key、场景配置
密码 Argon2 管理员密码哈希
图片 image / mozjpeg-rs / EXIF 尺寸探测、衍生图(缩略图 / 渐进式)、拍摄时间
前端嵌入 rust-embed(feature embed-ui) 发布版把 Vite 产物打进单 EXE
前端 React 19 + Vite 6 + Tailwind 4 + Motion 图库编辑、控制台、API 文档面板
安卓 UniApp(Vue) 可选移动端,见 uniapp-android/README.md

数据与目录

运行时数据默认在可执行文件旁的 data/(可用 DATA_DIR 覆盖):

data/
  app.db                 # SQLite 主库
  logs/image-host.log    # 运行日志
  gallery/               # 图库原图(按分类文件夹)
  gallery/_derived/      # 缩略图 / 渐进式衍生图
  images/                # 简易图床原图(若使用 /api/upload)

分类与磁盘对应:data/gallery/<分类文件夹>/。把图片拷进文件夹后,后台会周期扫描入库,也可在控制台「立即同步」。

鉴权模型

方式 用途
HttpOnly Cookie session=… Web 登录;API Key 管理等「仅 Web」接口
API Key pv_… 外部脚本 / App。Header:Authorization: Bearer pv_… 或 X-API-Key: pv_…
公开无鉴权 /s/、/g/、/i/、/api/v1/public/*、/api/health 等

/api/v1/upload 仅接受 API Key,不接受 Cookie。

图片链路设计要点

  • 原样存、原样流:上传不强制重编码,保留 progressive JPEG;支持 HTTP Range。
  • 衍生图异步生成:缩略图与渐进式 JPEG 后台队列生成,derivativesReady 标记就绪状态。
  • 内容去重:图库上传按内容哈希去重,duplicate: true 表示复用已有记录。
  • 外链 /s/{id}:固定公开 URL,优先返回渐进式 JPEG,未就绪时短暂回落原图。

目录结构

frontend/            # Web 前端(开发端口 3000)
backend/             # Rust API(默认端口 8765)
  embedded-ui/       # 发布时由前端 dist 拷入,供 rust-embed
  src/               # Axum 路由与业务
uniapp-android/      # 安卓客户端(独立工程)
.github/workflows/   # Release 编译二进制 + 推送 Docker
Dockerfile           # 基于预编译 linux 二进制的镜像
build-release.ps1    # Windows 本地打单文件 EXE

部署方式

1. Docker(推荐)

发布 Release 后,镜像推送到 GHCR:

docker pull ghcr.io/clockclock1/pixvault:latest

docker run -d --name pixvault \
  -p 8765:8765 \
  -v pixvault-data:/app/data \
  -e PUBLIC_BASE_URL=https://img.example.com \
  -e ADMIN_USERNAME=admin \
  -e ADMIN_PASSWORD='改成强密码' \
  ghcr.io/clockclock1/pixvault:latest

指定版本:

docker run -d -p 8765:8765 -v pixvault-data:/app/data \
  ghcr.io/clockclock1/pixvault:v0.1.0

docker-compose.yml 示例:

services:
  pixvault:
    image: ghcr.io/clockclock1/pixvault:latest
    ports:
      - "8765:8765"
    environment:
      BIND_ADDR: "0.0.0.0:8765"
      PUBLIC_BASE_URL: "https://img.example.com"
      ADMIN_USERNAME: admin
      ADMIN_PASSWORD: "改成强密码"
      RUST_LOG: "info"
    volumes:
      - pixvault-data:/app/data
    restart: unless-stopped

volumes:
  pixvault-data:

首次启动若库中无用户,会用 ADMIN_USERNAME / ADMIN_PASSWORD 创建管理员(默认 admin / admin123,生产务必修改)。

2. Release 二进制

从 Releases 下载对应平台产物:

产物 平台
pixvault-windows-amd64.exe Windows x64
pixvault-windows-arm64.exe Windows ARM64
pixvault-linux-amd64 Linux x64
pixvault-linux-arm64 Linux ARM64
pixvault-macos-amd64 macOS Intel
pixvault-macos-arm64 macOS Apple Silicon
# Linux / macOS
chmod +x pixvault-linux-amd64
PUBLIC_BASE_URL=https://img.example.com ./pixvault-linux-amd64

# Windows(PowerShell)
$env:PUBLIC_BASE_URL = "https://img.example.com"
.\pixvault-windows-amd64.exe

二进制已嵌入前端,浏览器访问 http://127.0.0.1:8765 即可。数据目录默认在 EXE 同级 data/。

创建 GitHub Release(published)会自动触发:

  1. Build Executables — 交叉编译上述 6 个产物并挂到 Release
  2. Docker Image — 推送 ghcr.io/clockclock1/pixvault:<tag> 与 latest

3. 本地编译单文件(Windows)

.\build-release.ps1

流程:frontend Vite 构建 → 拷贝到 backend/embedded-ui → cargo build --release --features embed-ui → 输出 release/image-host.exe。

4. 开发模式(前后端分离)

# 终端 1:后端
cd backend
cp .env.example .env   # 按需修改
cargo run

# 终端 2:前端
cd frontend
npm install
npm run dev
  • 前端:http://localhost:3000
  • 后端:http://0.0.0.0:8765
  • Vite 已将 /api、/i、/g、/s 代理到后端。

手动嵌入前端后编译后端:

cd frontend && npm ci && npm run build
rm -rf ../backend/embedded-ui && mkdir -p ../backend/embedded-ui
cp -R dist/. ../backend/embedded-ui/
cd ../backend
cargo build --release --features embed-ui

5. 反向代理(Nginx 示例)

外网 HTTPS 时,请把 PUBLIC_BASE_URL 设为对外域名,以便上传 API 返回完整外链。

server {
    listen 443 ssl http2;
    server_name img.example.com;

    # ssl_certificate     ...;
    # ssl_certificate_key ...;

    client_max_body_size 64m;

    location / {
        proxy_pass http://127.0.0.1:8765;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Range $http_range;
        proxy_set_header If-Range $http_if_range;
        proxy_buffering off;
    }
}

环境变量

变量 默认 说明
BIND_ADDR 0.0.0.0:8765 监听地址
PUBLIC_BASE_URL 由 BIND_ADDR 推导 外链完整前缀(上传 API / 随机图 JSON 中的 url)
DATA_DIR EXE 旁 ./data 数据与数据库目录
ADMIN_USERNAME admin 首次无用户时种子管理员
ADMIN_PASSWORD admin123 首次种子密码
RUST_LOG (crate 默认) 如 info / debug
CORS_ORIGIN 未设则开放 CORS 设为具体前端源时可带 Cookie 跨域
SESSION_DAYS 30 会话有效天数
COOKIE_SECURE 关 设为 1/true 时 Cookie 加 Secure

参考:backend/.env.example。


API 接口

控制台登录后打开 「API 接口」 可查看完整文档(参数表、响应示例、cURL / fetch / Python),并支持下载 JSON。下列为速查。

鉴权约定

# API Key(推荐外部调用)
Authorization: Bearer pv_你的密钥
# 或
X-API-Key: pv_你的密钥

在 Web:图库编辑 → API 接口 → 创建 Key。Key 管理接口仅 Cookie 会话可用。

错误响应一般为:

{ "error": "说明文字" }

系统 / 鉴权

方法 路径 鉴权 说明
GET /api/health 公开 健康检查 { ok, service }
GET /api/auth/status 公开 { needsBootstrap }
POST /api/auth/register 公开 仅无用户时可注册
POST /api/auth/login 公开 登录,Set-Cookie + 可选 token
POST /api/auth/logout 登录/Key 退出
GET /api/auth/me 登录/Key 当前用户
POST /api/auth/password 登录/Key 改密(成功后清会话)

API Key(仅 Web 登录)

方法 路径 说明
GET /api/keys 列出 Key(含完整 secret)
POST /api/keys 创建,body 可选 { "name": "脚本" }
DELETE /api/keys/{id} 物理删除

外部上传(仅 API Key)

curl -X POST "https://img.example.com/api/v1/upload" \
  -H "Authorization: Bearer pv_…" \
  -F "file=@/path/to/photo.jpg" \
  -F "categoryId=可选分类UUID"

响应示例:

{
  "id": "image-uuid",
  "url": "https://img.example.com/s/image-uuid",
  "contentType": "image/jpeg",
  "size": 102400,
  "progressive": true,
  "width": 1920,
  "height": 1080,
  "duplicate": false
}

url 为完整公开外链(PUBLIC_BASE_URL + /s/{id})。

公开分类随机图(无需鉴权)

先在分类管理中开启「公开分类」。

方法 路径 说明
GET /api/v1/public/categories 列出公开分类
GET /api/v1/public/random?categoryId= 随机一张;redirect=1 时 302 到图片
# JSON
curl "https://img.example.com/api/v1/public/random?categoryId=分类UUID"

# 直接当图片用
curl -L -o random.jpg \
  "https://img.example.com/api/v1/public/random?categoryId=分类UUID&redirect=1"

HTML:

<img src="https://img.example.com/api/v1/public/random?categoryId=分类UUID&redirect=1" alt="随机图" />

简易图床

方法 路径 鉴权 说明
POST /api/upload Key multipart file/image → 相对路径 /i/{id}
GET /api/images/{id} Key 元数据
GET /i/{id} 公开 原图流(支持 Range)
GET /i/{id}/{filename} 公开 带文件名的原图 URL

图库 Gallery

方法 路径 鉴权 说明
GET/POST /api/gallery/categories Key 列表 / 新建(可含 isPublic)
PUT/DELETE /api/gallery/categories/{id} Key 更新(含公开开关)/ 删除
GET/PUT /api/gallery/settings Key 展示设置
GET /api/gallery/images Key view=public|editor,可选 categoryId
POST /api/gallery/upload Key 入库图库,EXIF/mtime、去重
PUT/DELETE /api/gallery/images/{id} Key 改分类排序 / 删除
PUT /api/gallery/images/reorder Key { "ids": [...] }
POST /api/gallery/images/batch-delete Key { "ids": [...] }
POST /api/gallery/sync Key 磁盘 ↔ 数据库同步
GET /g/{id} 公开 ?v=original|progressive|thumb
GET /g/{id}/{filename} 公开 同上,带文件名

分类更新示例(开启公开):

curl -X PUT "https://img.example.com/api/gallery/categories/{id}" \
  -H "Authorization: Bearer pv_…" \
  -H "Content-Type: application/json" \
  -d '{"isPublic":true}'

分享外链

方法 路径 鉴权 说明
GET /api/share/{id} 公开 元数据 + imageUrl / thumbUrl
GET /api/share/{id}/image 公开 渐进式 JPEG
GET /api/share/{id}/thumb 公开 缩略图
GET /s/{id} 公开 推荐直链
GET /s/{id}/raw 公开 同 /s/{id}

Markdown:![photo](https://img.example.com/s/图片UUID)

场景(首页 3D 配置)

方法 路径 鉴权 说明
GET /api/scene 登录/Key 读取场景 JSON
PUT /api/scene 登录/Key 保存场景 JSON

请求体大小

默认 multipart / 请求体上限约 64MB(见服务端 DefaultBodyLimit)。反向代理请同步调大 client_max_body_size。


许可证

Apache License 2.0

About

映匣 PixVault 是面向个人与团队的自托管图床与图库系统。支持图库分类管理、公开/私有分组、外链直链引用,以及完整的 REST API(上传、分类、随机取图等)。Web 控制台管理内容与密钥,图片与数据本地存储,无需依赖第三方云存储。

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages