loopback-component-storage/lib/providers/filesystem/index.js

202 lines
6.0 KiB
JavaScript
Raw Normal View History

2013-06-24 21:07:12 +00:00
/**
* File system based on storage provider
*/
var fs = require('fs'),
path = require('path'),
2013-06-25 16:29:53 +00:00
async = require('async'),
File = require('./file').File,
Container = require('./container').Container;
2013-06-24 21:07:12 +00:00
module.exports = FileSystemProvider;
function FileSystemProvider(options) {
options = options || {};
this.root = options.root;
var stat = fs.statSync(this.root);
if (!stat.isDirectory()) {
throw new Error('Invalid directory: ' + this.root);
}
}
var namePattern = new RegExp('[^' + path.sep + '/]+');
function validateName(name, cb) {
if (!name) {
cb && process.nextTick(cb.bind(null, new Error('Invalid name: ' + name)));
return false;
}
var match = namePattern.exec(name);
if (match && match.index === 0 && match[0].length === name.length) {
return true;
} else {
cb && process.nextTick(cb.bind(null, new Error('Invalid name: ' + name)));
return false;
}
}
// Container related functions
FileSystemProvider.prototype.getContainers = function (cb) {
var self = this;
fs.readdir(self.root, function (err, files) {
2013-06-25 16:29:53 +00:00
var containers = [];
2013-06-24 21:07:12 +00:00
var tasks = [];
files.forEach(function (f) {
tasks.push(fs.stat.bind(null, path.join(self.root, f)));
});
async.parallel(tasks, function (err, stats) {
if (err) {
cb && cb(err);
} else {
stats.forEach(function (stat, index) {
if (stat.isDirectory()) {
2013-06-25 16:29:53 +00:00
var name = files[index];
var props = {name: name};
for (var p in stat) {
props[p] = stat[p];
}
2013-06-25 20:06:54 +00:00
var container = new Container(self, props);
2013-06-25 16:29:53 +00:00
containers.push(container);
2013-06-24 21:07:12 +00:00
}
});
2013-06-25 16:29:53 +00:00
cb && cb(err, containers);
2013-06-24 21:07:12 +00:00
}
});
});
}
FileSystemProvider.prototype.createContainer = function (options, cb) {
2013-06-25 16:29:53 +00:00
var self = this;
2013-06-24 21:07:12 +00:00
var name = options.name;
2013-06-25 16:29:53 +00:00
validateName(name, cb) && fs.mkdir(path.join(this.root, name), options, function (err) {
cb && cb(err, new Container(self, {name: name}));
});
2013-06-24 21:07:12 +00:00
}
FileSystemProvider.prototype.destroyContainer = function (containerName, cb) {
2013-06-25 16:29:53 +00:00
if (!validateName(containerName, cb)) return;
2013-06-24 21:07:12 +00:00
var dir = path.join(this.root, containerName);
fs.readdir(dir, function (err, files) {
var tasks = [];
files.forEach(function (f) {
2013-06-24 22:53:14 +00:00
tasks.push(fs.unlink.bind(null, path.join(dir, f)));
2013-06-24 21:07:12 +00:00
});
async.parallel(tasks, function (err) {
if (err) {
cb && cb(err);
} else {
fs.rmdir(dir, cb);
}
});
});
}
FileSystemProvider.prototype.getContainer = function (containerName, cb) {
2013-06-25 16:29:53 +00:00
var self = this;
if (!validateName(containerName, cb)) return;
2013-06-24 21:07:12 +00:00
var dir = path.join(this.root, containerName);
2013-06-25 16:29:53 +00:00
fs.stat(dir, function (err, stat) {
var container = null;
if (!err) {
var props = {name: containerName};
for (var p in stat) {
props[p] = stat[p];
}
container = new Container(self, props);
}
cb && cb(err, container);
});
2013-06-24 21:07:12 +00:00
}
// File related functions
FileSystemProvider.prototype.upload = function (options, cb) {
var container = options.container;
2013-06-25 16:29:53 +00:00
if (!validateName(container, cb)) return;
2013-06-24 21:07:12 +00:00
var file = options.remote;
2013-06-25 16:29:53 +00:00
if (!validateName(file, cb)) return;
2013-06-24 21:07:12 +00:00
var filePath = path.join(this.root, container, file);
var fileOpts = {flags: 'w+',
encoding: null,
mode: 0666 };
return fs.createWriteStream(filePath, fileOpts);
}
FileSystemProvider.prototype.download = function (options, cb) {
var container = options.container;
2013-06-25 16:29:53 +00:00
if (!validateName(container, cb)) return;
2013-06-24 21:07:12 +00:00
var file = options.remote;
2013-06-25 16:29:53 +00:00
if (!validateName(file, cb)) return;
2013-06-24 21:07:12 +00:00
var filePath = path.join(this.root, container, file);
var fileOpts = {flags: 'r',
autoClose: true };
return fs.createReadStream(filePath, fileOpts);
}
2013-06-25 20:06:54 +00:00
FileSystemProvider.prototype.getFiles = function (container, download, cb) {
if (typeof download === 'function' && !(download instanceof RegExp)) {
cb = download;
download = false;
}
2013-06-25 16:29:53 +00:00
var self = this;
if (!validateName(container, cb)) return;
2013-06-24 21:07:12 +00:00
var dir = path.join(this.root, container);
2013-06-25 16:29:53 +00:00
fs.readdir(dir, function (err, entries) {
var files = [];
2013-06-24 21:07:12 +00:00
var tasks = [];
2013-06-25 16:29:53 +00:00
entries.forEach(function (f) {
2013-06-24 22:53:14 +00:00
tasks.push(fs.stat.bind(null, path.join(dir, f)));
2013-06-24 21:07:12 +00:00
});
async.parallel(tasks, function (err, stats) {
if (err) {
cb && cb(err);
} else {
stats.forEach(function (stat, index) {
if (stat.isFile()) {
2013-06-25 16:29:53 +00:00
var props = {container: container, name: entries[index]};
for (var p in stat) {
props[p] = stat[p];
}
var file = new File(self, props);
files.push(file);
2013-06-24 21:07:12 +00:00
}
});
2013-06-25 16:29:53 +00:00
cb && cb(err, files);
2013-06-24 21:07:12 +00:00
}
});
});
}
FileSystemProvider.prototype.getFile = function (container, file, cb) {
2013-06-25 16:29:53 +00:00
var self = this;
if (!validateName(container, cb)) return;
if (!validateName(file, cb)) return;
2013-06-24 21:07:12 +00:00
var filePath = path.join(this.root, container, file);
2013-06-25 16:29:53 +00:00
fs.stat(filePath, function (err, stat) {
2013-06-25 17:44:37 +00:00
var f = null;
2013-06-25 16:29:53 +00:00
if (!err) {
var props = {container: container, name: file};
for (var p in stat) {
props[p] = stat[p];
}
2013-06-25 17:44:37 +00:00
f = new File(self, props);
2013-06-25 16:29:53 +00:00
}
2013-06-25 17:44:37 +00:00
cb && cb(err, f);
2013-06-25 16:29:53 +00:00
});
2013-06-24 21:07:12 +00:00
}
FileSystemProvider.prototype.removeFile = function (container, file, cb) {
2013-06-25 16:29:53 +00:00
if (!validateName(container, cb)) return;
if (!validateName(file, cb)) return;
2013-06-24 21:07:12 +00:00
var filePath = path.join(this.root, container, file);
fs.unlink(filePath, cb);
}