这款「外链图片自动本地化」插件(v1.0.0)专为 XIUNOX BBS 设计,全面支持发帖、回帖时的外链图片自动转存,并具备多图批量处理、失败容错、历史批量扫描、定时扫描及日志清理等完善功能。以下是该插件的详细功能与配置说明:
核心功能特性
自动转存与多图处理:在发帖、回帖或编辑时,自动检测内容中的外链图片(支持
<img>标签、BBCode[img]及裸链接),通过 cURL 下载并替换为本站附件地址。支持单帖多张图片的批量识别与去重,部分失败不影响其他图片。失败容错与重试:当遇到下载超时、403 或文件损坏时,系统会保留原始外链不变,不阻断发布流程,并在后台记录失败日志(包含原链接、错误原因及关联帖子ID)。后台支持对失败日志进行一键重试,自动更新原帖内容。
防盗链绕过与域名过滤:cURL 会自动携带从源 URL 提取的合理 Referer 及后台可配置的 User-Agent,提高抓取成功率。支持灵活的域名黑白名单配置(白名单仅转存指定域名,黑名单跳过如本站 CDN 的指定域名)。
多格式兼容与安全校验:智能识别 jpg/png/gif/webp/bmp/svg 格式,对非图片后缀但 Content-Type 为图片的外链进行智能识别与重命名。所有 POST 操作均带有 CSRF token 防护,并严格进行管理员权限检查。
历史批量与定时扫描:后台支持手动触发批量扫描(按版块/时间段筛选,带进度条与统计);同时支持通过系统 Cron 自动扫描最近 N 天的帖子/回复进行批量转存。
定时清理与用户反馈:通过系统 Cron 自动清理超过保留天数的失败日志和任务记录。转存过程中若有图片失败,发布成功后会以轻量级 Toast 通知用户“部分图片未能保存到本地”。
插件文件结构
plugin/oulin_imglocal/
├── conf.json # 插件元数据、hooks_rank
├── icon.png # 插件图标(64x64)
├── install.php # 建表 + 默认配置
├── uninstall.php # 删表 + 删除配置 + 清理日志文件
├── upgrade.php # 幂等迁移(预留)
├── setting.php # 后台设置控制器
├── readme.md # 使用说明
├── model/
│ └── ImglocalService.php # 核心业务:processContent、downloadAndSave、extractImageUrls、cronScan、autoCleanLogs
├── hook/
│ ├── model_inc_file.php # 注册 Service 类加载路径
│ ├── model_thread_create_end.php # 发帖后处理(模型层)
│ ├── model_post_create_end.php # 回帖后处理(模型层)
│ ├── model_thread_update_end.php # 编辑主题后处理(模型层)
│ ├── model_post_update_end.php # 编辑回复后处理(模型层)
│ ├── thread_create_thread_end.php # 发帖后处理(路由层)
│ ├── post_create_post_end.php # 回帖后处理(路由层)
│ ├── cron_cleanup.php # 定时清理日志 + 定时扫描
│ ├── message_start.htm # 失败 Toast 提示
│ └── lang_zh_cn_bbs.php # 翻译键定义
├── view/htm/
│ └── setting.htm # 后台页面(设置/批量/日志三标签)
└── static/
├── js/admin.js # 后台 JS(标签切换、AJAX 提交)
└── css/admin.css # 后台样式
数据库表设计
1. oulin_imglocal_log(失败日志表)
字段 | 类型 | 说明 |
|---|---|---|
id | int unsigned AUTO_INCREMENT | 主键 |
uid | int unsigned | 用户ID |
tid | int unsigned | 主题ID |
pid | int unsigned | 回复ID |
appid | int unsigned | 应用ID |
source_url | varchar(512) | 原始外链地址 |
error_reason | varchar(255) | 失败原因 |
retry_count | tinyint unsigned | 重试次数 |
created | int unsigned | 记录时间戳 |
2. oulin_imglocal_task(批量任务表)
字段 | 类型 | 说明 |
|---|---|---|
id | int unsigned AUTO_INCREMENT | 主键 |
uid | int unsigned | 操作用户ID |
type | varchar(32) | 扫描类型 |
fid | int unsigned | 版块ID |
start_time | int unsigned | 开始时间戳 |
end_time | int unsigned | 结束时间戳 |
total_count | int unsigned | 总数 |
success_count | int unsigned | 成功数 |
fail_count | int unsigned | 失败数 |
status | tinyint(1) | 0待执行 1执行中 2已完成 |
message | varchar(255) | 消息 |
created | int unsigned | 创建时间戳 |
配置与定时扫描流程
后台配置流程
进入后台「插件」→ 启用「外链图片自动本地化」插件(自动建表并写入默认配置)。
进入插件设置 → 勾选「启用外链图片本地化」并选择作用范围(新帖/回帖/编辑帖子/AppCenter应用)。
配置下载参数(单张最大大小、超时时间)及域名过滤(白名单/黑名单)。
配置定时扫描(开关、每次扫描数量、扫描时间范围)与日志清理(开关、保留天数)。
配置系统 Cron:
0 3 * * * cd /path/to/xiuno && php cron.php测试:发布含外链图片的帖子,验证图片是否自动转存为本地附件。
定时扫描流程 Cron 触发 hook/cron_cleanup.php 后调用 ImglocalService::cronScan():
读取配置(如扫描数量 N=50、时间范围=7天),计算时间起点 = 当前时间 - N 天。
查询最近 N 天的主题(LIMIT 50)→ 遍历 →
processContent()提取并转存外链图片 →thread_update()更新内容。查询最近 N 天的回复(LIMIT 50)→ 遍历 →
processContent()提取并转存外链图片 →post_update()更新内容。记录调试日志到
tmp/oulin_imglocal_debug.log。
扩展说明
如需扩展更多图片来源,可修改 ImglocalService::extractImageUrls() 方法,添加新的正则匹配规则;如需添加新的存储策略,可修改 saveAttachment() 方法,自定义存储路径和文件命名规则。


