之前博客的图片都是直接访问自己的服务器的, 无奈我的服务器带宽太小
大图加载缓慢
考虑使用一些第三方的对象存储服务来保存图片
比较主流的像是七牛云 又拍云, 都必须要绑定备案的域名才能访问
所以选择了网易云的对象存储服务( 现在只能通过企业认证后才能创建资源了, 好在创建的比较早 )
网易云的对象存储体验总体来讲还不错, 提供若干API以及针对不同语言的SDK包
简单整理了一下思路, 觉得同步图片的脚本还是用比较上手的js来写, 在服务器上用nodejs运行
1.对象存储的开通以及准备
创建一个桶对象, 之后会获得Endpoint以及访问域名
先记下来, 之后会用到
要绑定自定义的域名同样需要该域名是备案的
然后创建Access Key
注意 : 网易云的对象存储对于权限控制做的比较简单
这个key具备所有的API访问权限, 一定不要上传到公共仓库以免泄露
2.nodejs脚本编写以及调试
官方虽然有提供nodejs使用的sdk包, 但是年久失修, 官方已经基本不维护, 问题很多
调用起来非常麻烦
感谢 XGHeaven 大佬自己编写的sdk包 @xgheaven/nos-node-sdk
使用npm init
初始化一个nodejs项目
然后安装需要的依赖包npm install @xgheaven/nos-node-sdk optimist --save
optimist这个包可以方便处理运行时的命令行参数
为之后在持续集成当中的调用提供方便
list_images.js
我的博客图片都保存在 source/images 当中, 要与对象存储库中同步, 首先需要读取到本地有的图片文件列表
把这部分功能作为一个module封装一下
1 | const fs = require('fs') |
- 由于目录当中可能包含子目录, 所以需要进行递归遍历
- 使用nodejs提供的
crypto
模块来计算文件的md5哈希值
( 由于接口返回的数据也是md5的哈希值, 可以用它来比对文件差异 )
调用该模块暴露出的函数传入根目录和图片目录
比如imageFloder传入的是’images/‘
获得的是形如 [{name:’images/a.png’,md5:’xxx’},…] 的一个数组
auth_info.json
把访问对象仓库API需要的认证信息放在一个json文件当中
1 | { |
其中的字段根据第1步当中获得的写入
index.js
在这个模块里面大概需要做以下几件事
- 调用sdk当中提供的listObject接口获取到对象仓库里面已有的文件列表
- 将对象仓库的文件列表与本地文件列表进行比对, 包括文件名和hash值的比对
找出本地有但是对象仓库里面没有的, 或者都有但是hash值不同, 就是文件有差别的 - 调用sdk当中提供的putObject接口上传差异文件
1 | // 程序执行的传参 |
有以下几点注意:
- listObject 接口返回的数据不只有文件, 还有目录, 所以需要筛选到是文件的item, 因为这里我只是存图片, 就简单用正则来处理了
- listObject 接口调用时传入的prefix用于过滤item的前缀, 可以用于查询某个目录当中的所有对象
- limit参数用于指定获取最大的条数, 配合响应返回的nextMarker以及marker参数可以简单实现分页
但是实际使用发现官方的接口实现似乎存在bug, 导致获取到的内容不全
所以只好使用imagesList.length + 1
一次性获取所有了, 该值存在上限, 此处算是一个隐患 - 由于在服务器上使用jenkins构建博客, rootPath会不同 ( 取决于jenkins的工作空间 )
所以把该路径作为一个参数, 用于执行该脚本时从命令行传入optimist
库可以对传参进行校验, 如果指定参数未传入会抛出一个Error - putObject 接口传入的 objectKey 是保存在仓库中的位置, 比如可以是
images/sub/a.png
这里正好可以与listImages当中获取到的文件路径对应, 实现本地与对象仓库的目录结构完全一致 - prefix取决于图片目录在项目中所处的位置, 这个也可以考虑提取为参数传入, 让脚本更具备通用性
package.json
主要是加上执行index.js的script
1 | { |
3.持续集成
相关的js脚本在服务器上准备好之后, 就可以在持续集成当中写shell添加该脚本的调用了
1 | # 切换到nodejs脚本所在位置 |
WORKSPACE
是jenkins提供的一个环境变量, 代表工作空间分配给构建的目录的绝对路径
4.hexo静态化钩子函数编写
由于以往的文章当中的图片路径都是写的本地路径
形如/images/linux/nos/AccessKey.png
, 批量修改又不利于将来的迁移
所以参考了hexo的官方文档之后, 考虑在静态化过程当中添加一个过滤器
添加配置
在根目录的_config.yml
文件添加自定义的配置项
1 | # 图片存储仓库地址 |
filter.js
创建scripts目录 ( 可以是根目录或者主题目录下, 均有效 )
创建filter.js文件
1 | hexo.extend.filter.register('before_post_render', function(data){ |
before_post_render
这个钩子在文章开始渲染前执行
如果此时修改文章中的图片路径, 静态化之后的文件就是指向对象仓库的URL地址了
日常编写正则处理一下( 注意使用前瞻断言, 正则尽可能精确, 避免影响到其他内容 )
5.验证
以上所有做好之后, 在jenkins里面执行构建验证文件同步是否成功
之前的构建步骤没什么变化, 最后调用nodejs脚本只要成功把新图片上传上去就可以了
然后访问博客
查看文章页面中的图片路径是否正确