原文地址:https://www.jianshu.com/p/9b05e14ebc67
1. 介绍
使用LoopBack在进行项目开发时,如果有文件的上传下载功能需求,可以使用LoopBack提供的模块: loopback-component-storage。该模块不仅支持本地文件存储,还可以对接远程远程文件提供商如Amazon,Rackspace等,通过该模块你只需要填写几行简单的配置信息即可实现文件上传下载功能,可谓十分的便利。但是该模块不支持阿里云OSS,只能自己实现,已实现的版本地址为: loopback-component-storage。
注:本次分析源码版本为
e76d571a8c90cc4a1c50f2bf3966edaaf79eec40
这个commit
2. 官方示例演示
运行官方example
,跑起来会默认生成以下接口:
而这些接口对应的Model方法为:
API
datasource.json
的配置如下:
{
"db": {
"name": "db",
"connector": "memory"
},
"storage": {
"name": "storage",
"connector": "loopback-component-storage",
"provider": "filesystem",
"root": "./server/storage"
}
}
3. 源码分析
ok,现在开始查看loopback-component-storage源码。
打开package.json
,发现"main": "index.js",
查看index.js
发现了storage-connector
接着发现了storage-service
,在storage-service
看到(第68行):
StorageService.prototype.getContainers = function(cb) {
this.client.getContainers(function(err, containers) {
if (err) {
cb(err, containers);
} else {
cb(err, containers.map(function(c) {
return map(c);
}));
}
});
};
发现模型的方法如getContainers
等都是通过this.client
这个对象来执行,而这个对象是在通过factory.createClient(options)
创建的(第36行):
this.client = factory.createClient(options);
这个options就是在example项目定义的
datasource.json
的connector
为loopback-component-storage
的对象,即示例演示中的storage对象。
接着打开factory
的createClient
:
/**
* Create a client instance based on the options
* @param options
* @returns {*}
*/
function createClient(options) {
options = options || {};
# 1. 提取provider,如果不存在则默认为filesystem
var provider = options.provider || 'filesystem';
var handler;
try {
// 2. 先试着在本地providers下加载
handler = require('./providers/' + provider);
} catch (err) {
try {
// 3. 如果失败则加载外部模块
handler = require(provider);
if (!handler || !handler.createClient) {
// 4. handler不存在或不合法就直接使用pkcloud的storage
handler = require('pkgcloud').storage;
}
} catch (err) {
// 5. 再失败就直接使用pkcloud的storage
handler = require('pkgcloud').storage;
}
}
patchContainerAndFileClass(provider);
return handler.createClient(options);
}
重点关注第二步,先看下providers目录,发现只有一个filesystem文件夹,说明本地只支持provider
为filesystem
的配置,其他的均会抛出异常。现在看下filesystem目录下的index.js
文件(第26行):
module.exports.createClient = function(options) {
return new FileSystemProvider(options);
};
找到filesystem
类型的createClient
方法,创建的是一个FileSystemProvider
对象,在往下看(第97行):
FileSystemProvider.prototype.getContainers = function(cb) {
var self = this;
....
};
发现接口对应方法,也就是在这里定义的。
结论
到这里就可以知道如何自定义provider了:
- 在providers目录下创建自定义provider目录(如:aliyun)
- 在目录下
exports
出来的对象中实现createClient(options)
方法 - 在
createClient(options)
返回的对象中实现接口对应方法,如getContainers
等。
当然也可以直接全部写在一个文件里面,这里定义等步骤只是为了与已存在等模块风格一致。
4. 自定义
完整示例请参考:loopback-component-storage
5. Reference
- Storage component
- loopback-component-storage