nodebb-plugin-archcyril-r2
v1.0.10
Published
NodeBB v4.x upload provider for Cloudflare R2 (S3-compatible)
Maintainers
Readme
nodebb-plugin-archcyril-r2
NodeBB v4.x 插件,将上传文件存储到 Cloudflare R2(S3 兼容),支持 ACP 管理后台配置。
English | 中文
English
Features
- Upload images and files to Cloudflare R2
- ACP settings page for configuration
- Automatic cleanup on post/topic purge and delete
- Orphaned file cleanup on post edit
- Old avatar cleanup on profile picture change
- Multi-instance safe (shared DB snapshots with TTL)
- Streaming uploads (no full file in memory)
- i18n support (English, Chinese)
Installation
cd /path/to/nodebb
npm i /path/to/nodebb-plugin-archcyril-r2
./nodebb build
./nodebb restartEnable in ACP → Extend → Plugins, then click Settings to configure R2 credentials.
Configuration
All settings are configured through the ACP settings page (ACP → Plugins → Cloudflare R2 → Settings).
| Field | Required | Default | Description | |---|---|---|---| | Access Key ID | Yes | | R2 Access Key ID | | Secret Access Key | Yes | | R2 Secret Access Key | | Bucket | Yes | | R2 Bucket name | | Endpoint | Yes | | S3 API endpoint | | Region | No | auto | Region | | Upload Path | No | | Object key prefix | | Public Host | No | | CDN/custom domain URL | | Force Path Style | No | false | Use path-style S3 addressing | | Delete on soft delete | No | false | Delete objects when posts are soft-deleted | | Delete on topic soft delete | No | false | Delete objects when topics are soft-deleted |
How It Works
Upload flow: When a user uploads an image or file, the plugin intercepts via filter:uploadImage / filter:uploadFile hooks, streams the file to R2, and returns the public URL.
Cleanup flow: When posts/topics are purged or deleted, the plugin extracts R2 object keys from post content via regex and batch-deletes them. On post edit, orphaned files (referenced before but not after) are cleaned up.
Object key format: <uploadPath>/<slugified-name>-<uuid><ext>
Testing
Unit tests (no R2 connection needed):
npm testIntegration tests (requires real R2):
export TEST_R2_ACCESS_KEY_ID="your-key-id"
export TEST_R2_SECRET_ACCESS_KEY="your-secret"
export TEST_R2_BUCKET="your-bucket"
export TEST_R2_ENDPOINT="https://<account-id>.r2.cloudflarestorage.com"
export TEST_R2_HOST="https://cdn.example.com" # optional
npm run test:integrationHooks
| Hook | Type | Purpose |
|---|---|---|
| static:app.load | static | Register ACP route |
| filter:admin.header.build | filter | Add sidebar nav link |
| filter:uploadImage | filter | Upload images to R2 |
| filter:uploadFile | filter | Upload files to R2 |
| action:posts.purge | action | Cleanup on post purge |
| action:post.delete | action | Cleanup on post soft-delete |
| filter:post.edit | filter | Snapshot before edit |
| action:post.edit | action | Cleanup orphaned files |
| action:topics.purge | action | Cleanup on topic purge |
| action:topic.delete | action | Cleanup on topic soft-delete |
| filter:user.updateProfile | filter | Snapshot before avatar change |
| action:user.updateProfile | action | Cleanup old avatar |
| action:user.removeUploadedPicture | action | Cleanup removed avatar |
| action:settings.set | action | Invalidate settings cache |
中文
功能
- 将图片和文件上传到 Cloudflare R2
- ACP 管理后台设置页面
- 帖子/主题删除时自动清理 R2 对象
- 编辑帖子时清理不再引用的孤儿文件
- 更换头像时清理旧头像文件
- 多实例安全(共享数据库快照 + TTL)
- 流式上传(不占用全部内存)
- 支持中英文界面
安装
cd /path/to/nodebb
npm i /path/to/nodebb-plugin-archcyril-r2
./nodebb build
./nodebb restart在 ACP → Extend → Plugins 中启用插件,然后点击 Settings 配置 R2 凭证。
配置
所有设置通过 ACP 管理后台配置(ACP → Plugins → Cloudflare R2 → Settings)。
| 字段 | 必填 | 默认值 | 说明 | |---|---|---|---| | Access Key ID | 是 | | R2 Access Key ID | | Secret Access Key | 是 | | R2 Secret Access Key | | Bucket | 是 | | R2 Bucket 名称 | | Endpoint | 是 | | S3 API endpoint | | Region | 否 | auto | 区域 | | Upload Path | 否 | | 对象 key 前缀 | | Public Host | 否 | | CDN/自定义域名 URL | | Force Path Style | 否 | false | 使用路径风格寻址 | | 帖子软删除时清理 | 否 | false | 帖子软删除时删除 R2 对象 | | 主题软删除时清理 | 否 | false | 主题软删除时删除 R2 对象 |
工作原理
上传流程: 用户上传图片或文件时,插件通过 filter:uploadImage / filter:uploadFile hook 拦截,将文件流式传输到 R2,返回公开访问 URL。
清理流程: 帖子/主题被删除时,插件通过正则从帖子内容中提取 R2 对象 key 并批量删除。编辑帖子时,清理编辑前引用但编辑后不再引用的孤儿文件。
对象 key 格式: <uploadPath>/<slugified-name>-<uuid><ext>
测试
单元测试(无需 R2 连接):
npm test集成测试(需要真实 R2):
export TEST_R2_ACCESS_KEY_ID="your-key-id"
export TEST_R2_SECRET_ACCESS_KEY="your-secret"
export TEST_R2_BUCKET="your-bucket"
export TEST_R2_ENDPOINT="https://<account-id>.r2.cloudflarestorage.com"
export TEST_R2_HOST="https://cdn.example.com" # 可选
npm run test:integrationLicense
MIT
