halo-兰空图床商业版支持
一句话:这是一个 Halo 插件,把 Lsky Pro 兰空图床 作为 Halo 的附件存储后端;在开源版 v1 API 的基础上,本 fork 额外支持了商业版的 v2 API(
/api/v2/)。
一、项目简介
halo-lsky-pro 是一个 Halo 2.x 插件(原版由 @ichenhe 维护,本仓库为其 fork)。安装并启用后,Halo 后台「附件 - 存储策略」里会出现一个名为 Lsky Pro 兰空图床 的策略,配置好图床地址与 Token,文章图片就会直接存到 Lsky Pro,而不是本地或其他对象存储。
- 插件标识:
chenhe-lsky-pro,要求 Halo 版本>=2.22.0 - 原版能力:仅支持开源版 Lsky Pro 的 v1 API(
/api/v1/) - 本 fork 新增:同时支持商业版的 v2 API(
/api/v2/)
局限性(原版即存在):由于 Lsky Pro 本身限制,插件仅支持图片类附件,且不支持缩略图。
二、为什么要做这个 fork
原版 README 明确写着「暂不支持使用 v2 API(/api/v2/)的商业版本」。也就是说,如果你用的是付费 / 商业版兰空图床,它的接口走的是 /api/v2/,原版插件根本连不上——上传会失败或响应解析报错。
本 fork 的目标很直接:在尽量不破坏原版结构的前提下,把 v2 API 也接进来,让商业版用户也能用上。
三、新增功能(重点)
核心改动是引入一个 apiVersion 配置项(v1 / v2),其余逻辑都围绕它自动切换。
1. API 版本一键切换
存储策略里新增了「API 版本」下拉框:
v1(开源版):走/api/v1/,上传参数用strategy_idv2(商业版):走/api/v2/,上传参数用storage_id
LskyProProperties 中 apiVersion 默认 "v1";setLskyUrl() 现在会同时剥离结尾的 /api/v1 与 /api/v2 后缀,避免手滑填了完整 API 路径导致拼接出 /api/v2/api/v2 之类的问题。
2. 客户端按版本切换行为(LskyProClient)
final String apiPath = "v2".equals(apiVersion) ? "api/v2" : "api/v1";
this.isV2Api = "v2".equals(apiVersion);
final String baseUrl = server + (server.endsWith("/") ? "" : "/") + apiPath;
-
上传:v2 用
storage_id参数,v1 用strategy_idbodyBuilder.part(isV2Api ? "storage_id" : "strategy_id", strategyId); -
删除:v2 的 Lsky Pro 没有删除端点,因此
delete()在 v2 下直接return Mono.empty(),优雅跳过,不会报错。
3. 响应解析兼容 v2 格式
v1 与 v2 的返回结构差异很大,本 fork 做了对齐:
| 字段 | v1 API | v2 API |
|---|---|---|
| 访问链接 | links.url | public_url |
| 文件标识(用于删除 / 管理) | key | pathname / id |
| 显示名 | origin_name | name / filename |
| 状态 | 布尔 true | 字符串 "success" / "true" |
| 文件大小 | size(KB) | 不返回 |
buildAttachment() 据此兼容取值:链接优先取 public_url,否则 links.url;显示名优先 origin_name,否则 name / filename;标识优先 key,否则 pathname 或 id。
状态码的兼容尤其关键——v2 返回的是字符串 "success",于是 LskyResponse 把 status 改成 Object,并用 isSuccess() 同时兼容两种格式:
public boolean isSuccess() {
if (status instanceof Boolean b) return b;
if (status instanceof String s)
return "true".equalsIgnoreCase(s) || "success".equalsIgnoreCase(s);
return false;
}
4. 文件大小回退
v2 响应不含 size,UploadResponse 新增 fallbackSize 字段与 getSizeBytes():v1 把返回的 KB 换算成字节,v2 则回退到 fallback 值(当前实现传入 0L,即 v2 上传的附件在 Halo 中大小可能显示为 0,后续可优化为传入真实大小)。
5. 校验与运行时兼容
- 策略模板
policy-template-lskypro.yaml增加了「API 版本」选择器,并区分了 v1 / v2 的 Token、储存策略 ID 帮助文案;移除了仅适用于 v1 的 Token 格式校验。 - 校验接口(
PolicyConfigValidationController)在上传测试文件时同样传入apiVersion,且 v2 下删除会被安全跳过。 - 为兼容 Halo 2.25 运行时的 Jackson 版本,
status采用Object而非强类型,避免类加载冲突。
四、使用说明
- 下载本 fork 构建的
halo-lsky-pro-*.jar(或自行./gradlew build),在 Halo 后台「插件」安装并启用。 - 进入 附件 - 存储策略 - 新建存储策略,选择 Lsky Pro 兰空图床。
- 填写配置:
- Lsky Pro 地址:
https://img.example.com,不要带/或/api/vX后缀。 - API 版本:开源版选
v1,商业版选v2。 - API Token:
-
v1:通过接口获取
curl --location --request POST 'https://example.com/api/v1/tokens' \ --form 'email="your-email"' \ --form 'password="your-password"'返回形如
x|xxxxxxx。 -
v2:商业版后台「系统 - API Token」页面直接创建。
-
- 储存策略 ID:v1 对应
strategy_id,v2 对应storage_id,整数,可留空。 - 相册 ID:可选,仅付费 / 商业版生效。
- 实例 ID:可选,用于跨重装 / 换域名保持附件关联(建议手动固定)。
- Lsky Pro 地址:
- 点击「验证图床设置」测试连通性,保存即可。之后在文章里上传图片就会落到 Lsky Pro。
五、局限与注意事项
- 仅支持图片类附件(Lsky Pro 限制)。
- 不支持缩略图(Lsky Pro 只能生成单一固定尺寸缩略图,不满足 Halo 要求)。
- v2 删除不同步:商业版 v2 API 无删除端点,在 Halo 里删除附件时不会同步删除图床上的文件,图片仍保留在 Lsky Pro 中。
- v2 文件大小:v2 不返回大小,Halo 中该附件大小可能显示为 0。
- 若开启图床端的格式转换(图片压缩),会导致 Halo 显示的附件大小不正确。
- 开源版不支持相册 ID 参数(设置后无效)。
六、仓库与致谢
- 本 fork:github.com/lqbby/halo-lsky-pro(作者
@LQBBY) - 上游原版:ichenhe/halo-lsky-pro
- 许可证:GPL-3.0(沿用上游)
如果你也在用商业版兰空图床又想接 Halo,希望这个 fork 能省点事。有问题欢迎到本仓库提 issue。