我用 GitHub 作为存储开发了一个随机图片 API
本文介绍如何基于 GitHub 为图片存储,通过 API 随机返回可用的图片地址。
之所以研究它,主要是为了省钱,毕竟用啥 S3、七牛云、阿里云都是要花钱的。这套思路,gitee 应该也可以的,不过我看网上说,gitee 禁止图床开源啥的。而开发随机图片 API 只是为了验证是否能通过 GitHub 的 API 获取仓库中的文件,支持进一步开发其他管理工具。
前言
平时常用的桌面壁纸、终端背景图片,亦或是博客背景或文章封面,这些都离不开图片。于是,如何就想如何免费管理这些图片。
在网上找了一些免费的随机图片 API,大部分处于不可用的状态,或者是需要注册登录,创建 API Token。
作为一名老年程序员,自然就想能通过编程实现,实现图片自由。虽然也可以通过类似爬虫的思路实现,但还是希望都在自己的控制中,万一出现不好的图片就不好了。
免费 CDN 加速
我的博客图片一直在用 GitHub 存储,通过 jsdelivr CDN 加速。于是就思考,如果能获取到 GitHub 存储的文件列表,就可以实现一个图片服务。
简单说下 jsdelivr CDN,它支持对 GitHub 中文件的加速访问。如位于我的仓库下的图片,通过对地址转为为 jsdelivr CDN 地址。
如下的地址:
|
|
通过如下地址访问:
|
|
现在如果能顺利获取到仓库的图片文件列表,即可将 github 作为我们的图片图片存储,而无需花钱购买云存储实现。
查询 GitHub 图片列表
如何获得 GitHub 文件列表呢?这篇文章是讲如何将 GitHub 作为存储使用的,肯定要支持查询的,否则就没法玩了。
GitHub 支持接口获取仓库文件列表,基本流程是先通过某个接口查询仓库的信息,其中某个字段包含了最新的 hash,我们通过调用这个 hash,就能拿到这个 hash 下的文件列表。
仓库信息查看,即第一个接口,如下所示,如查询 user/repo 下某分支的情况。
|
|
JSON 返回体中,通过访问路径 .commit.commit.tree.url
拿到获取仓库文件列表的接口地址。其实主要是获取该分支最近的 commit hash。
演示案例,获取 github.com/poloxue/public_images
通过 httpie
执行请求,如下所示:
|
|
通过 jq 解析请求结果,再次通过 httpie 请求,命令如下:
|
|
如上的命令中通过 ?recursive=1
实现遍历子目录,通过 ‘.tree[].path’ 返回所有文件和目录。
返回结果如下:
|
|
特别说明:接口的返回其实有数量限制,但这个限制并不是很大,个人使用无需担心。如果想扩展扩展容量,可考虑创建多个分支,或者多个仓库啥的。
我的基本原则,把白嫖贯彻到底。
图片 API 服务
在了解如何使用GitHub 的接口后,我通过 gin 开发一个随机 API,创建了一个简单的 Random Image API。实现方案也不复杂,通过 GitHub 接口获取图片列表,随机选择其中一张图片,把它在仓库中的路径与 jsdelivr CDN 地址拼接,随机返回一个图片地址。
接口定义:
- Path: /image/random/{category}
- Parameters:
- category:str, 图片类型,即上面 github 仓库的子目名称;
- Return:
- image:str,图片地址,指定 category 类型下的一个图片地址;
接下来,我就来尝试实现这个服务。
main 函数
我直接使用 gin 框架开发这个 demo API。main
入口代码如下所示:
|
|
gin
创建和路由的部分没啥可介绍的。重点是,我创建了一个 ImageContainer
用于连接 GitHub 随机拿到随机的图片地址。
为什么我把 imageContainer
声明为全局变量,主要想着这样设计个本地缓存更容易些,不然一直请求 GitHub API 可不是个好事情,容易触发 GitHub 请求p频率限制。
ImageContainer
首先,定义下 ImageContainer
类型和它的创建函数,代码。
如下所示:
|
|
构造函数 NewImageContainer
创建时,要指定仓库 repo
和分支 branch
。ImageContainer
中的 images
字段用于按分类保存图片列表。对于 API 场景,使用 sync.Map
是个更好的选择,因为会存在并发竞争的问题。
随机图片的获取流程可描述为三个步骤,分别是查询最新 commit hash、基于 commit hash 获取 trees 图片列表和从图片列表中随机拿到一张图片返回。
随机图片 API 的核心部分代码,如下所示:
|
|
其他部分如 LastHash
、QueryImages
函数代码比较啰嗦,就不介绍了。不喜欢把太丑的代码贴在文章里。有兴趣可查看源码仓库 poloxue/random_image_from_github。
测试效果
请求示例,如下所示:
|
|
输出结果:
|
|
这只是服务的最小版本,还可以继续扩展,提供更多接口能力,甚至可以上传下载图片,还有生成缩略图等等。本案例只是测试代码,很多场景是没有实现的。
总结
本文介绍了如何基于 GitHub 实现一个简单的 random image API 服务,主要还是展示将 GitHub 作为替代 S3 存储服务使用。对于个人而言,肯定是能白嫖,就不要花钱,哈哈。
因为 GitHub 其实是提供了完整一套的增删改查接口的,基于它,我可以开发一个图床管理 app。还有,进一步,还可以基于它开发如 neovim、vscode 的博客图片插件,提升 markdown 写作效率。
我的博客地址:以 GitHub 作为图片存储创建随机图片 Service API