NodeBB 8: 使用CDN,将图片等附件资源上传至又拍云

Posted by River Yang on 2016-12-05

前几日 V2MM 和又拍云合作,又拍云赞助了 V2MM 免费的 CDN 存储服务,我因此写了一个叫 NodeBB Upyun Uploads 的 NodeBB 插件,具体安装和使用方式见 Github

为什么要使用又拍云呢?

又拍云是国内著名的云存储提供商,它们提供的服务当然不仅仅是 CDN, 具体见他们的官网。同时他们有开放且高度可扩展的API,为互联网提供基础服务,技术上高大上,服务上也有口皆碑。我写这个插件的目的是将网站上的图片和附件等资源分发到又拍云的 CDN 网络上去,既可减轻我的服务器的流量和压力,又可加快用户的访问速度,为何不用?

同时,又拍云在 CDN 服务上还有如下优势:

  • 健全的 API, 文档和第三方库;我这个插件就调用了 Upyun 的 node.js 库,根据他们的日志,这个库最早还是由第三方作者创造的 :)
  • 对资源权限有详细的控制,可以精细的控制外链权限,读写权限等;
  • 当然支持绑定自定义域名(要备案),默认域名也很好用,还支持 HTTPS 访问,这一点很良心;
  • 支持图片云处理,可以自动给图片加水印,作图,生成缩略图等,是不是很强大?

插件原理

打开插件目录下的 plugin.json 可以看到, 此插件主要是监听了 filter:uploadImagefilter:uploadFile 两个接口,这两个接口在很多地方都有调用,比如 src/controllers/admin/uploads.jssrc/controllers/api.jssrc/controllers/uploads.jssrc/topics/thumb.js 等,用户在设置Profile背景图片,发帖时上传的图片,Admin 设置的图片等等都会调用。

调用的方式也很有趣,如果有插件监听了这个接口的话, 系统默认的上传逻辑就不会执行,比如下面的逻辑处理发帖时上传的图片:

1
2
3
4
5
6
7
8
9
10
function (canUpload, next) {
if (!canUpload) {
return next(new Error('[[error:no-privileges]]'));
}
if (plugins.hasListeners('filter:uploadImage')) {
return plugins.fireHook('filter:uploadImage', {image: uploadedFile, uid: req.uid}, callback);
}
file.isFileTypeAllowed(uploadedFile.path, next);
},
...

所以本插件的原理就是监听 filter:uploadImagefilter:uploadFile 两个接口,将资源上传至又拍云,覆盖 NodeBB 原有的逻辑,做相应的处理。同样上传的方法分为上传图片和上传普通文件,上传之前会检查系统配置,上传方法调用 Upyun 的 nodejs 库,具体方法请看源码。
本插件还可以设置一系列配置,可以设置为环境变量,也可以在 Admin 中配置,保存进数据库。具体介绍见 Github

1
2
3
4
5
6
export UPYUN_OPERATER_NAME="operatername"
export UPYUN_OPERATER_PASSWORD="password"
export UPYUN_UPLOADS_BUCKET="mybucket"
export UPYUN_UPLOADS_PATH="path"
export UPYUN_ENDPOINT="v0.api.upyun.com"
export UPYUN_HOST="hostname domain"

欢迎使用,如有疑问或发现BUG,可以在 Github 或 V2MM 上向我反馈。