jdf-upload
Version:
jdf upload module
214 lines (198 loc) • 5.91 kB
JavaScript
;
const path = require('path');
const fs = require('fs');
const glob = require('glob');
const fsPath = require('fs-path');
const FTP = require('./node-ftp/connection');
const Base = require('./baseUploader');
const base = require('jdf-utils').base;
const logger = require('jdf-log');
module.exports = class Ftp extends Base {
constructor(options) {
// host user password 必须提供
super(options);
this.client = new FTP();
logger.debug('ftp mode used');
}
connect() {
return new Promise((resolve, reject) => {
if (this.client.connected) {
resolve();
} else {
this.client
.on('ready', resolve)
.on('error', (err) => {
this.client.end();
reject(err);
});
this.client.connect(this.options);
}
});
}
mkdir(source) {
return new Promise((resolve, reject) => {
if (typeof source === 'undefined') {
this.client.end();
reject(new Error('jdf error [ftp.mkdir] source is not exists'));
} else {
this.connect()
.then(() => {
this.client.mkdir(source, true, (err) => {
if (err) {
this.client.end();
reject(err);
} else {
resolve();
}
});
});
}
});
}
get(source, target) {
return new Promise((resolve, reject) => {
this.connect()
.then(() => {
this.client.get(source, (err, stream) => {
if (err) {
this.client.end();
reject(new Error(`[ftp.get] - ${target} - ${err.message}`));
} else {
stream.pipe(fs.createWriteStream(target));
stream.once('end', () => {
resolve();
});
}
});
});
});
}
put(source, target) {
return new Promise((resolve, reject) => {
this.client.put(source, target, (err) => {
if (err) {
this.client.end();
reject(new Error(`jdf error [ftp.put] - ${target} - ${err}`));
} else {
resolve();
}
});
});
}
list(source) {
if (typeof source === 'undefined') {
source = './';
}
return new Promise((resolve, reject) => {
this.connect()
.then(() => {
this.client.list(source, (err, list) => {
if (err) {
this.client.end();
reject(err);
} else {
if (list && list.length > 0) {// eslint-disable-line
const filesList = [];
list.forEach((data) => {
let fileType = '';
if (data.type === '-') {
fileType = 'file';
} else if (data.type === 'd') {
fileType = 'dir';
}
filesList.push({
name: data.name,
type: fileType,
})
});
resolve(filesList);
} else {
this.client.end();
reject(new Error(`'${source}' is not exists`));
}
}
});
})
})
}
download(source, target) {
return new Promise((resolve, reject) => {
this.list(source)
.then((data) => {
if (data instanceof Error) {
reject(data);
} else {
fsPath.mkdirSync(target); // 先创建本地的文件夹,再下载
let serverNum = 0;
let localNum = 0;
data.filter(item => item.type === 'file')
.reduce((prev, item) => {
return prev.then(() => {
serverNum += 1;
const sourcePut = base.joinPath(source, item.name);
const targetPut = base.joinPath(target, item.name);
return this.get(sourcePut, targetPut, () => {
localNum += 1;
});
});
}, Promise.resolve())
.then(function() {
this.client.end();
if (serverNum === localNum) {
resolve();
}
});
}
});
});
}
upload(root, target) {
const files = this.getFiles(root, target);
// 远程先创建文件夹,再创建文件
return new Promise((resolve) => {
this.connect()
.then(() => {
return files.reduce((prev, info) => {
return prev.then(() => {
logger.verbose(`${info.type} source:${info.source} target:${info.target}`);
if (info.type === 'dir') {
return this.mkdir(info.target);
}
return this.put(info.source, info.target);
})
}, Promise.resolve()).then(() => {
this.client.end();
resolve();
});
});
});
}
/**
* 遍历本地文件,获取所有的文件和文件夹,类似walk的功能
* @param root
* @param target
*/
getFiles(root, target) {
const files = glob.sync('**', {
cwd: root,
mark: true,
});
// 如果只上传一个文件,那么增加他的父文件夹,确保node-ftp先创建文件夹再创建文件
if (files.length === 1) {
const stat = fs.statSync(path.resolve(root, files[0]));
if (stat.isFile()) {
files.unshift(`${path.dirname(files[0])}/`);
}
}
return files.map((file) => {
const subSourcePath = path.resolve(root, file);
const subTargetPath = base.pathJoin(target, file);
const type = fs.statSync(subSourcePath).isDirectory() ? 'dir' : 'file';
return {
source: subSourcePath,
target: subTargetPath,
type: type,
};
});
}
}