Random Image API
一个自托管的随机图片 API,带管理后台。基于 Node.js + Express,无需数据库,图片存在本地文件系统。适合个人图床、壁纸站等场景。
功能
- 多图库管理,支持
pc(横屏)和mobile(竖屏)分类 - 随机图 API,默认 302 跳转到绝对图片 URL,并支持返回图片本体或 JSON
- 图片 API 默认不缓存,静态图片文件长缓存,适合配合 CDN 使用
- 管理后台:上传、预览、筛选、排序、批量删除
- 上传时校验真实文件头,拒绝危险文件类型
- Cookie Session、CSRF、Helmet、限流、CORS
路径约定
应用挂载在 /image 子路径下:
| 路径 | 用途 |
|---|---|
/image | 首页 |
/image/admin | 管理后台 |
/image/images/... | 图片静态访问 |
/image/api/... | API 接口 |
部署
Docker Hub 镜像(推荐)
镜像地址:docker.io/charyeahowo/nyaovo-random-image-api:latest
docker compose 部署(点击展开)
创建 docker-compose.yml,复制以下内容,修改 ADMIN_PASSWORD 和 SESSION_SECRET:
services:
nyaovo-random-image-api:
image: charyeahowo/nyaovo-random-image-api:latest
container_name: nyaovo-random-image-api
ports:
- "3400:3000"
volumes:
- ./images:/app/public/images
environment:
PORT: 3000
PUBLIC_BASE_URL: http://localhost:3400
IMAGE_ROOT: public/images
CACHE_TTL_SECONDS: 60
RATE_LIMIT_WINDOW_MS: 60000
RATE_LIMIT_MAX: 120
ADMIN_USERNAME: admin
ADMIN_PASSWORD: changeme # ← 务必修改
SESSION_SECRET: please-change-this # ← 务必修改
ADMIN_PATH: /image/admin
MAX_FILE_SIZE_MB: 10
MAX_UPLOAD_FILES: 20
CORS_ORIGIN: "*"
restart: unless-stopped
docker compose up -d
容器启动时会自动修复
./images目录权限,无需手动 chown。如果是从旧版本升级,首次启动可能需要几秒完成权限修复。
访问 http://localhost:3400/image,后台 http://localhost:3400/image/admin。
docker run 部署(点击展开)
docker run -d \
--name nyaovo \
-p 3400:3000 \
-v ./images:/app/public/images \
-e ADMIN_PASSWORD=your-password \
-e SESSION_SECRET=your-secret \
-e PUBLIC_BASE_URL=http://localhost:3400 \
--restart unless-stopped \
charyeahowo/nyaovo-random-image-api:latest
挂载的
images目录需要写权限,不要加:ro。
本地构建部署(点击展开)
git clone https://github.com/charyeahowo/nyaovo-random-image-api.git
cd nyaovo-random-image-api
cp .env.example .env
# 编辑 .env,至少修改 ADMIN_PASSWORD 和 SESSION_SECRET
docker compose up -d --build
如需使用本地构建而非远程镜像,请将 docker-compose.yml 中的 image 行替换为:
build:
context: .
dockerfile: Dockerfile
1Panel 部署(点击展开)
- 新建 Docker Compose 编排,上传项目或 Git 拉取
- 使用项目自带
docker-compose.yml,创建.env文件填写环境变量 - 启动后在 OpenResty / Nginx 配置反向代理绑定域名
本地运行
npm install
cp .env.example .env # 编辑配置
npm start # 或 npm run dev 热更新
默认账号 admin,默认密码 changeme。
Cloudflare Worker + R2 公开 API
如果只想把随机图公开访问迁移到 Cloudflare,保留现有后台和 Docker 部署不变,可以使用新增的 Worker + R2 方案:
- Worker 代码和 Wrangler 配置位于 `cloudflare/`
- 迁移脚本:
npm run cloudflare:manifest - 部署说明见 `cloudflare/README.md`
第一阶段只承载 /image/api/... 和 /image/images/... 的公开访问能力,后台管理仍使用当前 Express 项目。
EdgeOne Pages + Edge Functions 公开 API
如果主要面向国内访问加速,或想用腾讯云 EdgeOne Pages 做轻量公开访问层,可以使用新增的 EdgeOne 方案:
- EdgeOne 代码、Pages 配置和文档位于 `edgeone/`
- 迁移脚本:
npm run edgeone:manifest - 部署说明见 `edgeone/README.md`
第一阶段只迁移随机图、图库列表、图片列表、统计和健康检查等公开接口;后台管理仍继续使用当前 Express 项目。
环境变量
| 变量 | 默认值 | 说明 |
|---|---|---|
PORT | 3000 | 容器内监听端口 |
PUBLIC_BASE_URL | http://localhost:3000 | JSON 返回的 URL 前缀 |
IMAGE_ROOT | public/images | 图片存放目录 |
CACHE_TTL_SECONDS | 60 | 缓存刷新间隔(秒) |
RATE_LIMIT_WINDOW_MS | 60000 | 限流窗口(毫秒) |
RATE_LIMIT_MAX | 120 | 窗口内最大请求数 |
ADMIN_USERNAME | admin | 用户名 |
ADMIN_PASSWORD | changeme | 密码 |
SESSION_SECRET | please-change-this | Session 密钥 |
ADMIN_PATH | /image/admin | 后台路径 |
MAX_FILE_SIZE_MB | 10 | 单文件大小限制(MB) |
MAX_UPLOAD_FILES | 20 | 单次批量上传数量 |
CORS_ORIGIN | * | 页面和后台接口的 CORS 允许来源;图片 API 与静态图片固定允许跨域访问 |
目录结构
.
├── src
│ ├── index.js
│ ├── config.js
│ ├── imageStore.js
│ ├── routes/
│ ├── middleware/
│ └── utils/
├── public
│ ├── images/ # 图片存储
│ │ └── {gallery}/
│ │ ├── pc/
│ │ └── mobile/
│ └── assets/ # CSS, JS
├── views/ # HTML 模板
├── Dockerfile
├── docker-compose.yml
└── package.json
API
GET /image/api/random
随机返回一张图片。默认 302 跳转到真实图片文件的绝对 URL,适合 CDN 缓存 /image/images/... 下的图片资源;随机入口本身不缓存。图片 API 和最终静态图片响应都会带 Access-Control-Allow-Origin: *,方便主题、前端页面和跨域图片加载使用。
| 参数 | 可选值 | 默认值 | 说明 |
|---|---|---|---|
gallery | 图库名 | 全部 | 指定图库 |
device | pc / mobile / all | all | 设备类型 |
type | image / json / redirect / pc / mobile | redirect | 返回格式;pc / mobile 兼容部分主题写法,会按设备类型处理 |
device 优先级高于 type。例如 /image/api/random?device=mobile&type=mobile 会按 device=mobile 选择手机竖屏图片,并使用默认 302 跳转返回;未知 type 会被忽略并按默认 redirect 处理。
返回格式说明:
| type | 返回内容 | Content-Type |
|---|---|---|
image | 图片二进制流 | image/* |
json | 图片元数据 JSON | application/json |
redirect | 302 跳转到绝对图片 URL | - |
默认访问 /image/api/random 等价于 /image/api/random?type=redirect。如需直接返回图片本体,可使用 ?type=image;如需 JSON,可使用 ?type=json;如需显式跳转,可使用 ?type=redirect。
缓存与跨域:
/image/api/...响应统一设置Cache-Control: no-store, no-cache, must-revalidate, proxy-revalidate/image/images/...静态图片统一设置Cache-Control: public, max-age=31536000, immutable- 图片 API、302 响应和静态图片响应统一带
Access-Control-Allow-Origin: *
JSON 响应示例:
{
"url": "https://example.com/image/images/anime/pc/001.webp",
"gallery": "anime",
"device": "pc",
"filename": "001.webp",
"size": 123456,
"width": 1920,
"height": 1080,
"type": "webp",
"total": 12
}
API 调用示例
| 接口 | 适用场景 |
|---|---|
GET /image/api/random | 默认 302 跳转到真实图片文件,适合 CDN 缓存图片路径 |
GET /image/api/random?gallery=anime | 指定图库随机出图,适合分类壁纸轮播 |
GET /image/api/random?gallery=anime&device=pc | 指定图库 + 横屏,适合桌面端背景 |
GET /image/api/random?gallery=anime&device=mobile | 指定图库 + 竖屏,适合手机端背景 |
GET /image/api/random?type=pc | 兼容部分主题参数写法,等价于按桌面横屏随机 |
GET /image/api/random?type=mobile | 兼容 Sakurairo 等主题参数写法,等价于按手机竖屏随机 |
GET /image/api/random?type=json | 获取图片元数据,适合前端自行渲染 |
GET /image/api/random?type=image | 直接返回图片本体,适合不需要 CDN 跳转缓存的场景 |
GET /image/api/random?type=redirect | 302 跳转,适合 <img src> 直接引用 |
GET /image/api/:gallery | 图库快捷接口,等同于 ?gallery=xxx |
GET /image/api/galleries | 获取所有图库统计,适合管理面板展示 |
GET /image/api/list?limit=100 | 分页获取图片列表,适合后台管理 |
GET /image/api/stats | 全局统计信息,适合监控面板 |
GET /image/health | 健康检查,适合 Docker/K8s 探针 |
图片管理
- 支持格式:jpg, jpeg, png, webp, gif, avif
- 上传时自动识别真实格式,扩展名错误也会纠正
- 图库名仅支持小写字母、数字、下划线、短横线
- 也可直接把图片放入
public/images/{gallery}/pc或mobile目录,程序会自动扫描
安全提醒
- 部署前务必修改
ADMIN_PASSWORD和SESSION_SECRET - 建议修改
ADMIN_PATH为不易猜到的路径 - 反代中可为后台路径添加 IP 白名单或 Basic Auth
- 请勿上传未授权图片用于公开服务

Comments NOTHING