release: v1.3.0 — 整站备份恢复、跨后端同步与任务中心
ci / ci (22, ubuntu-latest) (push) Canceled after 0s
GitHub Release / release (push) Canceled after 0s
Publish Docker image / build (linux/amd64, ubuntu-latest, amd64) (push) Canceled after 0s
Publish Docker image / build (linux/arm64, ubuntu-24.04-arm, arm64) (push) Canceled after 0s
Publish Docker image / merge (push) Canceled after 0s

This commit is contained in:
O96u committed 2026-09-07 17:05:12 +08:00
1 parent b05d572221
commit f17d79b236
72 files changed
+4312 -559

No files matched your search

-2
View File
@@ -34,7 +34,6 @@ const zhSidebar = [
text: '升级',
items: [
{ text: '更新日志', link: '/guide/changelog' },
{ text: 'v1.2 迁移', link: '/guide/migration' },
{ text: '常见问题', link: '/guide/faq' }
]
}
@@ -71,7 +70,6 @@ const enSidebar = [
text: 'Upgrade',
items: [
{ text: 'Changelog', link: '/en/guide/changelog' },
{ text: 'v1.2 migration', link: '/en/guide/migration' },
{ text: 'FAQ', link: '/en/guide/faq' }
]
}
+1 -4
View File
@@ -159,15 +159,12 @@ Version history and notable changes. The full log is also in the repo root [CHAN
### Changed
- All images under `data/images/`; legacy `blog/` / `twikoo/` need migration
- All images under `data/images/`; parallel top-level folders beside `images` are no longer used
### Added
- CLI: `docker exec pichost migrate` / `migrate --apply`
- Startup index sync (disk scan, legacy key normalization, orphan cleanup)
See [v1.2 migration](./migration.md).
---
## [1.1.x] summary
+10 -10
View File
@@ -61,21 +61,21 @@ Recommended: run PicHost on origin; use **proxied DNS** (and optional **R2** sto
- Always open admin on the **site hostname**, not mixed with `localhost`
- See [Dual-domain separation](./domain-separation.md)
## Undeletable gallery items after v1.2 upgrade?
## Undeletable gallery items?
Likely **orphan index** rows (no file on disk). Startup sync removes them on restart. See [v1.2 migration](./migration.md#step-2-startup-index-sync-automatic).
Likely **orphan index** rows (no file on disk). Startup sync removes them on restart; you can also delete them from the gallery.
## Do I still need `data/blog/` after migration?
## How do I back up or migrate the full site?
After `migrate --apply`, files live under `data/images/blog/`. Remove leftover empty dirs after backup if you like; dirs with non-image files are kept by the CLI.
From v1.3.0, use **Storage → Backup & migration**, or CLI:
## Object storage only — run migrate?
```bash
docker exec pichost backup-export
docker exec pichost backup-restore /data/backups/pichost-xxx.phost.tar.gz
docker exec pichost storage-sync --from local --to s3-xxx --dry-run
```
No. Skip the CLI; startup sync focuses on local `data/images/` scanning.
## Replace old image URLs in posts?
Use `data/mapping.json` from `migrate` preview. Keys are **storage paths**, not full legacy URLs. See [Migration](./migration.md#urls).
Packages include the database and all images but **not** cloud storage secrets — re-enter them on the Storage page after restore. See [Storage → Backup & migration](./storage.md#backup--migration-v130).
## Skip login during development?
+9 -7
View File
@@ -33,10 +33,18 @@ See `docker-compose.yml` in the repository.
## First-time setup
1. Open your instance URL (Docker default `http://<host>:6892`).
2. Complete `/setup` with admin username and password.
2. On `/setup`, choose **Create admin** or **Restore backup**:
- **Create admin** — username, password, optional registration and dual-domain options.
- **Restore backup** — upload a `.phost.tar.gz` full-site package (replaces current data; re-enter cloud storage secrets after restore).
3. (Optional) Configure site URL, image URL, Referer rules — see [Environment variables](./configuration.md) and [Dual-domain separation](./domain-separation.md).
4. Upload from the home page; use the top nav for **Gallery**, **Storage** (admin), **Settings**, and **API**.
| Create admin | Restore from backup |
| :----------: | :-----------------: |
| ![Setup](/screenshots/setup.png) | ![Setup restore](/screenshots/setup-restore.png) |
For an already-initialized instance, use [Storage → Backup & migration](./storage.md#backup--migration-v130) instead of `/setup`.
## Sign in
Management pages (upload, gallery, settings, etc.) require login. Enter username and password, complete the verification challenge, then click **Sign in**.
@@ -80,12 +88,6 @@ docker exec pichost clear-domains
Local: `npm run clear-domains`. See [FAQ — Admin 404 after dual-domain setup](./faq.md#admin-404--locked-out-after-dual-domain-setup).
## Upgrading to v1.2.0
If `data/` has legacy top-level folders next to `images` (e.g. `blog/`, `twikoo/`), read the [v1.2 migration guide](./migration.md) first.
Object-storage-only or files already under `data/images/` — pull the new image and restart.
## Next steps
- [Local development](./local-dev.md)
+7 -3
View File
@@ -12,16 +12,20 @@ Welcome to the PicHost user guide. This site is the single source of truth; the
## Screenshots
**main** has no public demo. Below are current product screenshots (v1.2.5+).
**main** has no public demo. Below are current product screenshots (v1.3.0+).
| API | Gallery |
| :-: | :-----: |
| API | Gallery (detail) |
| :-: | :--------------: |
| ![API](/screenshots/api.png) | ![Gallery](/screenshots/gallery.png) |
| Storage | Settings |
| :-----: | :-------: |
| ![Storage](/screenshots/storage.png) | ![Settings](/screenshots/settings-en.png) |
| First-time setup | Restore from backup |
| :--------------: | :-----------------: |
| ![Setup](/screenshots/setup.png) | ![Setup restore](/screenshots/setup-restore.png) |
| Activity log |
| :----------: |
| ![Activity log](/screenshots/logs.png) |
+1 -2
View File
@@ -30,7 +30,6 @@ Open `http://localhost:3000/setup` to create the admin account. Data directory d
| `npm run reset-password` | Reset password (optional username) |
| `npm run slider` | Reset login verification to local slider |
| `npm run clear-domains` | Clear site/image URL settings from DB (recover from dual-domain lockout) |
| `npm run migrate` | Preview legacy dir migration (`-- --apply` to run) |
## Dev-only variables
@@ -53,4 +52,4 @@ npm run docs:build
npm run docs:preview
```
Sources live in `docs-site/`; screenshot sources are in `docs/screenshots/` (including `login.png`), copied to `docs-site/public/screenshots/` before build. Live docs: <https://o96u.github.io/PicHost/>
Sources live in `docs-site/`; screenshot sources are in `docs/screenshots/` (including `login.png`, `setup.png`, `setup-restore.png`, etc.), copied to `docs-site/public/screenshots/` before build. Live docs: <https://o96u.github.io/PicHost/>
-129
View File
@@ -1,129 +0,0 @@
# v1.2.0 local disk migration guide
From v1.2.0, **all local image files** live under `data/images/`; SQLite `keys` also start with `images/`. Legacy top-level folders next to `images` (e.g. `data/blog/`, `data/twikoo/`) are no longer used.
Migration is **two steps**: run the **CLI** to move files on disk, then let **startup sync** align the SQLite index.
---
## Migrating from other image hosts (EasyImage, Lsky, Chevereto, …)
There is **no** dedicated “pull from URLs” or “import via vendor API” tool. Moving from **legacy PicHost** or **another self-hosted** install uses the same **local file** workflow:
1. Locate the **image files** on the old server (copy the tree, not just the database).
2. Place them under PicHost `data/` as a **top-level folder** next to `images` (any name — it becomes `images/{name}/...`).
3. Run `migrate` / `migrate --apply`, then restart PicHost.
| Source | Typical path on old server | After copy into PicHost |
| ------ | -------------------------- | ----------------------- |
| PicHost v1.1.x | `data/blog/`, `data/twikoo/` | Already under `data/` → run `migrate` |
| EasyImage(s) | `i/` or `upload/` | e.g. `data/easyimage/` → `migrate` |
| Lsky | `public/uploads/` etc. | e.g. `data/lsky/` → `migrate` |
| Chevereto etc. | `images/` or `content/` | e.g. `data/chevereto/` → `migrate` |
| Custom | your folder name | `data/your-folder/` → `migrate` |
The CLI scans **every top-level directory under `data/` except `images`**, not only `blog` / `twikoo`.
**Limits:** files only — accounts, tokens, and old public URLs are not imported. `mapping.json` maps old **storage keys**, not full old-site URLs. For S3/R2-only legacy hosts, sync blobs to `data/…` or attach the bucket in PicHost **Storage** settings.
---
## Layout before and after
### Before (typical v1.1.x)
```
/data
├── pichost.db
├── blog/
│ └── 2026/08/TeKJ2fD6cB6j.webp
├── twikoo/
└── images/
```
Index keys might look like `blog/2026/08/TeKJ2fD6cB6j.webp`.
### After (v1.2.0)
```
/data
├── pichost.db
├── mapping.json
└── images/
├── blog/
│ └── 2026/08/TeKJ2fD6cB6j.webp
└── twikoo/
```
Index key: `images/blog/2026/08/TeKJ2fD6cB6j.webp`.
---
## Step 1: CLI file migration
Run **before or after** upgrading the image; backup `data/` first.
```bash
docker exec pichost migrate # preview + mapping.json
docker exec pichost migrate --apply # move files
```
Local: `npm run migrate` / `npm run migrate -- --apply`.
| Item | Behavior |
| ---- | -------- |
| Scan | Every top-level directory under `data/` **except `images`** |
| Target | `data/images/{original-top-dir}/{relative-path}` |
| Extensions | jpg, jpeg, png, webp, gif, svg, ico |
| Sidecar | `.meta.json` next to an image is moved if present |
| Other files | Not moved; parent directory kept if anything remains |
| Mapping | `data/mapping.json` — old key → new key |
Script: `server/cli/migrate-to-single-images.mjs`.
---
## Step 2: Startup index sync (automatic)
Runs on every start (`npm run dev`, Docker). No manual command.
```text
[INFO] 开始同步图片索引:扫描本地磁盘 ...
[INFO] 磁盘扫描完成:...
[INFO] 开始归一化遗留图片路径 ...
[INFO] 开始校验索引与磁盘一致性,清理无文件的孤儿记录
[INFO] 图片索引同步结束
```
| Step | Purpose |
| ---- | ------- |
| Scan `data/images/` | Insert missing index rows for files on disk |
| Normalize legacy keys | `blog/...` → `images/blog/...` when files are in place |
| Purge orphans | Remove index rows with no file on disk |
| Repair Content-Type | Fix `application/octet-stream` entries |
The CLI only **moves files**. Index alignment runs at startup — **restart** after `migrate --apply`.
---
## Recommended upgrade flow
1. Backup `data/`.
2. `docker exec pichost migrate` — review output and `mapping.json`.
3. `docker exec pichost migrate --apply`.
4. Deploy v1.2.0 and restart.
5. Check logs for successful index sync.
6. Use `mapping.json` to update external URLs if needed.
Skip step 1 if you only use object storage or everything is already under `data/images/`.
---
## URLs
| Old key | `blog/TeKJ2fD6cB6j.webp` |
| New key | `images/blog/TeKJ2fD6cB6j.webp` |
With “hide folder” mode, short URLs like `/TeKJ2fD6cB6j.webp` may still resolve by filename. Use `mapping.json` for bulk replacements.
Chinese version: [v1.2 迁移指南](/guide/migration)
+39 -4
View File
@@ -54,13 +54,48 @@ Copied links use **IMAGE_BASE_URL**. “Hide folder prefix” may shorten URLs;
## Usage & gallery filter
- Per-backend usage on the Storage page
- Gallery filters by **storage backend** and **upload source**; grid/list view toggle
- Gallery filters by **storage backend** and **upload source**; grid/list view toggle; click a thumbnail for the detail modal (dimensions, storage path, link formats)
## Backup
## Backup & migration (v1.3.0+)
Back up `data/images/`, `data/pichost.db`, and bucket objects.
The **Backup & migration** panel has three action cards and a paginated **Recent jobs** table below:
Upgrading from v1.1.x with parallel folders: [v1.2 migration](./migration.md).
| Feature | Description |
| ------- | ------------- |
| **Create site backup** | Export `.phost.tar.gz` with `pichost.db` and all images (including objects on cloud backends); shows estimated size and package contents |
| **Restore from backup** | Upload locally or pick an existing package under `data/backups/`, preview, then confirm; skip or overwrite conflicting images |
| **Cross-backend sync** | Copy images between configured backends and update the index; shows pending count/size, dry-run, optional delete-source and set-default |
![Backup & migration](/screenshots/storage.png)
- Exports are saved under `data/backups/`; only one backup/migration job may run at a time
- Job list supports pagination; download exports, view restore summaries, retry failed sync jobs
- Packages **do not** include cloud storage secrets — re-enter them on the Storage page after restore
- Uninitialized instances can use the **Restore backup** tab on `/setup` (always overwrite mode)
![Setup restore](/screenshots/setup-restore.png)
### CLI
```bash
docker exec pichost backup-export
docker exec pichost backup-restore /data/backups/pichost-xxx.phost.tar.gz
docker exec pichost backup-restore /data/backups/pichost-xxx.phost.tar.gz --overwrite
docker exec pichost storage-sync --from local --to s3-xxx --dry-run
docker exec pichost storage-sync --from local --to s3-xxx --set-default
```
Local development (project root):
```bash
npm run backup-export
npm run backup-restore -- data/backups/pichost-xxx.phost.tar.gz
npm run storage-sync -- --from local --to s3-xxx --dry-run
```
### Manual backup
You can still back up `data/images/`, `data/pichost.db`, and bucket objects directly; prefer the full-site export above.
## See also
+1 -4
View File
@@ -159,15 +159,12 @@ PicHost 版本历史与重要变更说明。完整记录亦见仓库根目录 [C
### 变更
- 图片统一存放在 `data/images/`;遗留 `blog/`、`twikoo/` 等并列目录需迁移
- 图片统一存放在 `data/images/`;不再使用与 `images` 并列的顶层目录
### 新增
- CLI:`docker exec pichost migrate` / `migrate --apply`
- 启动时自动同步图片索引(扫描磁盘、归一化遗留 key、清理孤儿记录)
详见 [v1.2 迁移](./migration.md)。
---
## [1.1.x] 摘要
+10 -10
View File
@@ -62,21 +62,21 @@ docker exec pichost clear-domains
- 后台请用 **网站域名** 打开,不要用 `localhost` 混用
- 见 [双域名分离](./domain-separation.md)
## 升级 v1.2 后图库有删不掉的记录?
## 图库有删不掉的记录?
可能是 **孤儿索引**(有记录无文件)。重启后启动同步会自动清理;也可手动删除仅索引项。见 [v1.2 迁移](./migration.md#第二步启动时自动同步索引)。
可能是 **孤儿索引**(有记录无文件)。重启后启动同步会自动清理;也可在图库中手动删除。
## 遗留 `data/blog/` 目录还要吗?
## 如何备份与迁移整站?
执行 `migrate --apply` 后文件已迁入 `data/images/blog/`。若原目录只剩空壳或非图片文件,可自行备份后删除;迁移脚本不会删除仍含非图片文件的目录。
v1.3.0 起在 **存储** 页使用「备份与迁移」面板,或 CLI:
## 只用对象存储需要跑 migrate 吗?
```bash
docker exec pichost backup-export
docker exec pichost backup-restore /data/backups/pichost-xxx.phost.tar.gz
docker exec pichost storage-sync --from local --to s3-xxx --dry-run
```
不需要。图片在桶内时跳过 CLI;启动同步主要面向本地 `data/images/` 磁盘扫描。
## 如何替换博客里的旧图片 URL?
使用 `data/mapping.json`(`migrate` 预览时生成)批量替换旧 key。注意映射的是 **存储 key**,不是完整旧站 URL。见 [迁移指南](./migration.md#外链与直链)。
备份包含数据库与全部图片,**不含** 云存储密钥;恢复后请在存储页重新填写。详见 [存储 → 备份与迁移](./storage.md#备份与迁移v130)。
## 开发时如何跳过登录?
+9 -7
View File
@@ -33,10 +33,18 @@ docker compose up -d
## 首次设置
1. 访问实例 URL(Docker 默认 `http://<主机>:6892`)。
2. 在 `/setup` 填写管理员用户名与密码。
2. 在 `/setup` 选择 **创建管理员** 或 **从备份恢复**:
- **创建管理员**:填写用户名与密码,可选开放注册、双域名等。
- **从备份恢复**:上传 `.phost.tar.gz` 整站备份包(覆盖当前数据;云存储密钥需恢复后重新填写)。
3. (可选)配置网站域名、图片域名、防盗链等 — 详见 [环境变量](./configuration.md) 与 [双域名分离](./domain-separation.md)。
4. 登录后可在首页上传图片;顶栏可进入 **图库**、**存储**(管理员)、**设置**、**API**。
| 创建管理员 | 从备份恢复 |
| :--------: | :--------: |
| ![首次设置](/screenshots/setup.png) | ![从备份恢复](/screenshots/setup-restore.png) |
已初始化实例请使用 [存储 → 备份与迁移](./storage.md#备份与迁移v130) 恢复,而非 setup 页。
## 登录
访问上传、图库、设置等管理页面前需登录。在登录卡片中填写用户名与密码,完成人机验证后点击 **登录**。
@@ -83,12 +91,6 @@ docker exec pichost clear-domains
本地:`npm run clear-domains`。详见 [常见问题 — 双域名配置后后台 404](./faq.md#双域名配置后后台-404-进不去)。
## 升级到 v1.2.0
若 `data/` 下存在与 `images` 并列的遗留目录(如 `blog/`、`twikoo/`),升级前请阅读 [v1.2 迁移指南](./migration.md)。
仅对象存储、或图片已在 `data/images/` 下时,拉取新镜像并重启即可。
## 下一步
- [本地开发](./local-dev.md) — `npm run dev` 与 `.env`
+6 -2
View File
@@ -12,9 +12,9 @@
## 截图预览
**main** 分支暂无公网演示,以下为当前产品界面(v1.2.5+)。
**main** 分支暂无公网演示,以下为当前产品界面(v1.3.0+)。
| API | 图库 |
| API | 图库(详情) |
| :-: | :-: |
| ![API](/screenshots/api.png) | ![图库](/screenshots/gallery.png) |
@@ -22,6 +22,10 @@
| :------: | :--------: |
| ![存储管理](/screenshots/storage.png) | ![设置与偏好](/screenshots/settings.png) |
| 首次设置 | 从备份恢复 |
| :------: | :--------: |
| ![首次设置](/screenshots/setup.png) | ![从备份恢复](/screenshots/setup-restore.png) |
| 操作日志 |
| :------: |
| ![操作日志](/screenshots/logs.png) |
+1 -2
View File
@@ -30,7 +30,6 @@ npm run dev
| `npm run reset-password` | 重置密码(可选用户名) |
| `npm run slider` | 将登录验证重置为本地滑块 |
| `npm run clear-domains` | 清除数据库中的网站域 / 图片域配置(双域名锁死时恢复) |
| `npm run migrate` | 预览遗留目录迁移(加 `-- --apply` 执行) |
## 开发专用环境变量
@@ -53,4 +52,4 @@ npm run docs:build # 构建静态站点
npm run docs:preview # 预览构建结果
```
文档源码在 `docs-site/`;截图源文件在 `docs/screenshots/`(含 `login.png` 登录页),构建前会复制到 `docs-site/public/screenshots/`。在线文档:<https://o96u.github.io/PicHost/>
文档源码在 `docs-site/`;截图源文件在 `docs/screenshots/`(含 `login.png`、`setup.png`、`setup-restore.png` 等),构建前会复制到 `docs-site/public/screenshots/`。在线文档:<https://o96u.github.io/PicHost/>
-176
View File
@@ -1,176 +0,0 @@
# v1.2.0 本地磁盘迁移指南
v1.2.0 起,**所有本地图片文件**统一放在 `data/images/` 下;SQLite `images` 表中的 `key` 也以 `images/` 开头。旧版在 `data/blog/`、`data/twikoo/` 等与 `images` **并列的顶层目录**不再符合新模型。
迁移分 **两步**:先用手动 CLI **搬文件**,再由服务 **启动时自动同步索引**。
---
## 从其它图床迁入(EasyImage / 兰空 / Chevereto 等)
**没有**单独的「一键从外链拉取」或「对接某某图床 API」工具。从 **PicHost 旧版** 或其它自托管图床迁入,走的是同一套 **本地文件迁移**:
1. 在旧图床服务器上找到图片**物理目录**(整目录拷贝,不要只拷数据库)。
2. 把该目录放到 PicHost 的 `data/` 下,作为与 `images` **并列的顶层文件夹**(文件夹名任意,会保留为 `images/{文件夹名}/...`)。
3. 执行 `migrate` / `migrate --apply`,再重启 PicHost。
### 常见来源示例
| 来源 | 典型图片目录(在旧服务器上) | 放入 PicHost 后示例 |
| ---- | ---------------------------- | ------------------- |
| PicHost v1.1.x | `data/blog/`、`data/twikoo/` | 已在 `data/` 下,直接 `migrate` |
| EasyImage / EasyImages | `i/` 或安装目录下的 `upload/` | 拷到 `data/easyimage/` 再 `migrate` |
| 兰空图床 (Lsky) | `public/uploads/` 等 | 拷到 `data/lsky/` 再 `migrate` |
| Chevereto 等 | `images/` 或 `content/` | 拷到 `data/chevereto/` 再 `migrate` |
| 任意自定义目录 | 你的顶层文件夹名 | 拷到 `data/你的目录名/` 再 `migrate` |
脚本会扫描 `data/` 下**除 `images` 外所有顶层目录**里的图片,不限于 `blog` / `twikoo`。子目录结构会原样保留在 `images/{顶层名}/` 下。
### 操作示例(Docker)
```bash
# 在宿主机:把从旧图床打包的目录放进挂载卷(名称自定)
# 例如:./data/easyimage/2026/01/photo.jpg
docker exec pichost migrate # 预览
docker exec pichost migrate --apply
# 重启容器 → 启动日志会补全 SQLite 索引
```
### 说明与限制
- **只迁移文件**:旧图床的账号、Token、外链 URL **不会**自动导入;`mapping.json` 里的 key 是「旧磁盘相对 key → 新 key」,**不是**旧站完整 URL,替换外链需自行对照。
- **对象存储**:若旧图床图片在 S3/R2 桶里,请用桶工具同步到本地 `data/某目录/`,或直接在 PicHost **存储**页配置同一桶(不经过本 CLI)。
- **已直接在 `data/images/` 下**:无需 `migrate`,重启后启动同步会自动建索引。
---
## 存储结构对比
### 迁移前(v1.1.x 常见)
```
/data
├── pichost.db
├── blog/
│ └── 2026/08/TeKJ2fD6cB6j.webp
├── twikoo/
│ └── xxx.webp
└── images/ # 可能已有部分新图
└── ...
```
SQLite 中 `key` 可能是 `blog/2026/08/TeKJ2fD6cB6j.webp`(与磁盘顶层目录一致)。
### 迁移后(v1.2.0)
```
/data
├── pichost.db
├── mapping.json # CLI 生成:旧 key → 新 key(供替换外链)
└── images/
├── blog/
│ └── 2026/08/TeKJ2fD6cB6j.webp
├── twikoo/
│ └── xxx.webp
└── ... # 新上传:images/随机ID.webp 或 images/年/月/随机ID.webp
```
对应 `key`:`images/blog/2026/08/TeKJ2fD6cB6j.webp`。
---
## 第一步:CLI 迁移磁盘文件
在 **升级镜像之前或之后**均可执行;建议在升级前完成,并先备份整个 `data/` 目录。
### Docker
```bash
# 预览:列出待迁移文件,写入 data/mapping.json(旧 key → 新 key)
docker exec pichost migrate
# 确认无误后执行文件移动
docker exec pichost migrate --apply
```
### 本地开发
```bash
npm run migrate # 预览
npm run migrate -- --apply # 执行
```
### 脚本行为
| 项目 | 说明 |
| ---- | ---- |
| 扫描范围 | `data/` 下**除 `images` 外所有顶层目录**(不限于 blog/twikoo) |
| 迁移目标 | `data/images/{原顶层目录名}/{相对路径}` |
| 图片类型 | `.jpg` `.jpeg` `.png` `.webp` `.gif` `.svg` `.ico` |
| 伴随文件 | 若存在同名的 `.meta.json` 会一并移动 |
| 非图片文件 | 不移动;若目录内仍有其它文件,**保留原目录**不删除 |
| 映射表 | `data/mapping.json`,例如 `"blog/foo.webp": "images/blog/foo.webp"` |
脚本路径:`server/cli/migrate-to-single-images.mjs`。
---
## 第二步:启动时自动同步索引
每次 PicHost 启动(`npm run dev`、Docker 容器启动)会自动执行,**无需手动命令**。日志示例:
```text
[INFO] 开始同步图片索引:扫描本地磁盘 {"path":".../data/images/"}
[INFO] 磁盘扫描完成:已补全缺失索引 {"inserted":3}
[INFO] 开始归一化遗留图片路径(如 blog/ → images/blog/)
[INFO] 遗留路径归一化完成:无需调整
[INFO] 开始校验索引与磁盘一致性,清理无文件的孤儿记录
[INFO] 孤儿索引清理完成:未发现孤儿记录
[INFO] 开始修复存量 Content-Type 元数据
[INFO] Content-Type 修复完成:无需修复
[INFO] 图片索引同步结束
```
| 步骤 | 作用 |
| ---- | ---- |
| 扫描 `data/images/` | 磁盘上有、索引里没有 → **补全** `images` 表 |
| 归一化遗留 key | 将 `blog/...` 等旧 key 更新为 `images/blog/...`(文件已在正确路径时) |
| 清理孤儿索引 | 索引里有记录、磁盘无文件 → **删除**幽灵记录(避免图库出现删不掉的项) |
| 修复 Content-Type | 修正错误的 `application/octet-stream` |
CLI 只负责**搬文件**;索引对齐、遗留 key、孤儿记录由启动同步处理。执行 `migrate --apply` 后**重启一次**服务即可。
---
## 推荐升级流程
1. **备份** `data/`(含 `pichost.db` 与各目录)。
2. `docker exec pichost migrate` 预览,检查输出与 `mapping.json`。
3. `docker exec pichost migrate --apply` 执行迁移。
4. 拉取 / 部署 **v1.2.0** 镜像并重启容器。
5. 查看启动日志,确认「图片索引同步结束」无报错。
6. 用 `mapping.json` 批量替换博客、Twikoo 等外链中的旧路径(若需要)。
仅使用对象存储、或图片早已全部在 `data/images/` 下时,**跳过第一步**;第二步仍会在启动时运行,通常几秒内完成且无变更日志。
---
## 外链与直链
| 场景 | 说明 |
| ---- | ---- |
| 旧 key | `blog/TeKJ2fD6cB6j.webp` |
| 新 key | `images/blog/TeKJ2fD6cB6j.webp` |
| 隐藏目录模式 | 若开启「隐藏 images 前缀」,短链可能为 `/TeKJ2fD6cB6j.webp`;服务按文件名反查索引 |
| 替换建议 | 以 `mapping.json` 为准;或重新在图库复制新链接 |
---
## 相关命令
| 命令 | 说明 |
| ---- | ---- |
| `docker exec pichost migrate` | 预览磁盘迁移 |
| `docker exec pichost migrate --apply` | 执行磁盘迁移 |
| `docker exec pichost reset-password` | 重置密码(与迁移无关) |
+43 -7
View File
@@ -56,17 +56,53 @@ PicHost 支持 **本地磁盘** 与 **S3 兼容对象存储**(Cloudflare R2、
## 用量与筛选
- 存储页展示各后端用量(本地扫描目录,对象存储查询 API)
- 图库可按 **存储后端**、**上传来源** 筛选,支持网格/列表视图切换
- 图库可按 **存储后端**、**上传来源** 筛选,支持网格/列表视图切换;点击图片打开详情弹窗(尺寸、存储路径、多格式链接复制)
## 备份
## 备份与迁移(v1.3.0+)
请同时备份:
存储页 **备份与迁移** 面板包含三张功能卡与下方 **最近任务** 列表:
- `data/images/`(本地后端)
- `data/pichost.db`
- 各云桶中的对象
| 能力 | 说明 |
| ---- | ---- |
| **创建站点备份** | 导出 `.phost.tar.gz`,含 `pichost.db` 与全部图片(含云存储中的对象);展示预计体积与备份包含项 |
| **从备份恢复** | 本地上传或选择 `data/backups/` 内已有包,预检后确认;可选跳过/覆盖冲突图片 |
| **跨后端同步** | 在已配置后端间拷贝图片并更新索引;展示待迁移数量与体积,支持预检、删源、设默认 |
从 v1.1.x 升级且存在 `data/blog/` 等并列目录时,见 [v1.2 迁移](./migration.md)。
![备份与迁移](/screenshots/storage.png)
- 导出文件保存在 `data/backups/`;后端同一时间仅允许一个进行中的备份/迁移任务
- 任务列表支持分页,可下载导出包、查看恢复结果、重试失败的同步任务
- 备份包 **不含** 云存储 Access Key / Secret Key,恢复后请在存储页重新填写
- 未初始化实例可在 **setup** 页 **从备份恢复** 标签上传整站包(始终覆盖模式)
![从备份恢复(setup)](/screenshots/setup-restore.png)
### CLI
```bash
# 导出整站备份
docker exec pichost backup-export
# 从备份恢复(默认跳过冲突图片)
docker exec pichost backup-restore /data/backups/pichost-xxx.phost.tar.gz
docker exec pichost backup-restore /data/backups/pichost-xxx.phost.tar.gz --overwrite
# 跨后端同步
docker exec pichost storage-sync --from local --to s3-xxx --dry-run
docker exec pichost storage-sync --from local --to s3-xxx --set-default
```
本地开发(项目根目录):
```bash
npm run backup-export
npm run backup-restore -- data/backups/pichost-xxx.phost.tar.gz
npm run storage-sync -- --from local --to s3-xxx --dry-run
```
### 手动备份
仍可同时备份 `data/images/`(本地后端)、`data/pichost.db` 与各云桶中的对象;推荐使用上文整站导出。
## 相关