Skip to content

Commit 83aaf5a

Browse files
committed
feat: 优化上传功能
1 parent e5750b1 commit 83aaf5a

File tree

3 files changed

+86
-28
lines changed

3 files changed

+86
-28
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ $ cshell upload -a accessKey -s secretKey -b bucket -p prefix/ -o originDirector
3434
-f, --force Whether to overwrite upload.
3535
-z --zone [value] Online zone. one of "huad"、"huab"、"huan"、"beim"、"z0"、"z1"、"z2"、"na0"
3636
-o, --originDirectoryPath [value] Directory's path of the files to upload, default is "dist"
37+
-n, --concurrencyNumber [value] Concurrency number of action. default is 40
3738
-h, --help output usage information
3839
```
3940

bin/cshell-upload.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ program
1818
"-o, --originDirectoryPath [value]",
1919
'Directory\'s path of the files to upload, default is "dist"'
2020
)
21+
.option(
22+
"-n, --concurrencyNumber [value]",
23+
'Concurrency number of action. default is 40'
24+
)
2125
.parse(process.argv);
2226

2327
if (isEmpty(program.accessKey)) {

lib/scripts/upload.js

Lines changed: 81 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ let mac;
1010
let originDirectoryPath; // 源目录路径
1111
let zone;
1212
let force;
13+
let concurrencyNumber = 40; // 并发数
14+
const chain = [];
1315

1416
const zoneMap = {
1517
huad: "Zone_z0",
@@ -28,15 +30,14 @@ const zoneMap = {
2830
* @param {String} fileName 文件名
2931
* @param {String} prefix 前缀
3032
*/
31-
function uploadFile(filedir, fileNameIn, prefix = "") {
33+
function uploadFile(filedir, fileNameIn, prefix = "", callback) {
3234
let fileName = prefix + fileNameIn;
3335
const options = {
3436
scope: force ? `${bucket}:${fileName}` : bucket
3537
};
3638
const putPolicy = new qiniu.rs.PutPolicy(options);
3739
const uploadToken = putPolicy.uploadToken(mac);
3840
const putExtra = new qiniu.form_up.PutExtra();
39-
4041
const config = new qiniu.conf.Config();
4142
if (!isEmpty(zone)) {
4243
config.zone = qiniu.zone[zoneMap[zone]];
@@ -50,14 +51,17 @@ function uploadFile(filedir, fileNameIn, prefix = "") {
5051
respInfo
5152
) {
5253
if (respErr) {
54+
log.fail(`Upload ${bucket} ${fileName} fail.`);
5355
log.error(respErr);
5456
}
5557
if (respInfo.statusCode == 200) {
56-
log.success(`Upload ${bucket} ${fileName} success`);
58+
log.success(`Upload ${bucket} ${fileName} success.`);
59+
callback();
5760
} else {
5861
log.fail(
5962
`Upload ${bucket} ${fileName} fail. ${respInfo.statusCode} ${respBody.error}`
6063
);
64+
callback();
6165
}
6266
});
6367
}
@@ -67,36 +71,38 @@ function uploadFile(filedir, fileNameIn, prefix = "") {
6771
* @param {String} filePath 初始目录
6872
*/
6973
function fileDisplay(filePath) {
70-
fs.readdir(filePath, function(err, files) {
71-
if (err) {
72-
log.error(err);
73-
} else {
74-
files.forEach(function(filename) {
75-
const filedir = path.join(filePath, filename);
76-
fs.stat(filedir, function(eror, stats) {
77-
if (eror) {
78-
log.error(error);
79-
} else {
80-
const isFile = stats.isFile();
81-
const isDir = stats.isDirectory();
82-
if (isFile) {
83-
const fileName = filedir
84-
.replace(`${originDirectoryPath}${path.sep}`, "")
85-
.replace(/\\/g, "/");
86-
uploadFile(filedir, fileName, prefix);
87-
} else if (isDir) {
88-
fileDisplay(filedir);
89-
}
90-
}
91-
});
92-
});
93-
}
94-
});
74+
try {
75+
const files = fs.readdirSync(filePath);
76+
files.forEach(function(filename) {
77+
const filedir = path.join(filePath, filename);
78+
try {
79+
const stats = fs.statSync(filedir);
80+
const isFile = stats.isFile();
81+
const isDir = stats.isDirectory();
82+
if (isFile) {
83+
const fileName = filedir
84+
.replace(`${originDirectoryPath}${path.sep}`, "")
85+
.replace(/\\/g, "/");
86+
chain.push((...args) =>
87+
uploadFile(filedir, fileName, prefix, ...args)
88+
);
89+
} else if (isDir) {
90+
fileDisplay(filedir);
91+
}
92+
} catch (error) {
93+
log.error(error);
94+
}
95+
});
96+
} catch (error) {
97+
log.error(error);
98+
}
9599
}
96100

97101
function upload(program) {
98102
const accessKey = program.accessKey;
99103
const secretKey = program.secretKey;
104+
const pConcurrencyNumber = Number(program.concurrencyNumber);
105+
100106
bucket = program.bucket;
101107
prefix = isEmpty(program.prefix) ? "" : program.prefix;
102108
force = !!program.force;
@@ -109,12 +115,59 @@ function upload(program) {
109115
);
110116
}
111117

118+
if (Number.isInteger(pConcurrencyNumber)) {
119+
concurrencyNumber = pConcurrencyNumber;
120+
}
121+
112122
originDirectoryPath = path.resolve(
113123
!isEmpty(program.originDirectoryPath)
114124
? program.originDirectoryPath.replace(/\\/g, "/")
115125
: "dist"
116126
);
117127
fileDisplay(originDirectoryPath);
128+
batchExec(chain, successCallback);
129+
}
130+
131+
/**
132+
* 成功回调
133+
* @param {Number} length
134+
*/
135+
function successCallback(length) {
136+
log.success(`Done, all ${length} files upload success.`);
137+
}
138+
139+
/**
140+
*
141+
* @param {Array} chain 执行队列
142+
*/
143+
async function batchExec(chain, callback) {
144+
const chainLen = chain.length;
145+
const promises = {};
146+
let diff;
147+
let promisesLen;
148+
let promiseKey;
149+
let startNum = 0;
150+
let timer = setInterval(() => {
151+
if (chain.length === 0) {
152+
clearInterval(timer);
153+
timer = null;
154+
return;
155+
}
156+
diff = concurrencyNumber - Object.keys(promises).length;
157+
if (diff <= 0) return;
158+
chain.splice(0, diff).forEach(fn => {
159+
promiseKey = startNum++;
160+
promises[promiseKey] = true;
161+
(function(promiseKey) {
162+
fn(() => {
163+
delete promises[promiseKey];
164+
if (Object.keys(promises).length === 0) {
165+
callback(chainLen);
166+
}
167+
});
168+
})(promiseKey);
169+
});
170+
}, 0);
118171
}
119172

120173
module.exports = upload;

0 commit comments

Comments
 (0)