tools_batch_files 1.0.31 → 1.0.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/audioFn/audioBatch.js +98 -51
- package/utils/logger.js +44 -7
- package/utils/settleFiles.js +31 -0
package/package.json
CHANGED
@@ -1,11 +1,18 @@
|
|
1
1
|
#!/usr/bin/env node
|
2
2
|
const generateUniqueHash = require("../../utils/index");
|
3
|
-
const {
|
3
|
+
const {
|
4
|
+
disposeError,
|
5
|
+
readExcel,
|
6
|
+
logger,
|
7
|
+
successLogger,
|
8
|
+
} = require("../../utils/logger");
|
4
9
|
|
5
10
|
const {
|
6
11
|
findFileInDir,
|
7
12
|
logFileSize,
|
8
13
|
ensureDirSync,
|
14
|
+
isExist,
|
15
|
+
readTxt,
|
9
16
|
} = require("../../utils/settleFiles");
|
10
17
|
const ffmpeg = require("fluent-ffmpeg");
|
11
18
|
const fs = require("fs");
|
@@ -273,7 +280,13 @@ const postData = (dataParams, indexFilePath) => {
|
|
273
280
|
/**
|
274
281
|
* 接口重试机制
|
275
282
|
*/
|
276
|
-
async function postDataWithRetry(
|
283
|
+
async function postDataWithRetry(
|
284
|
+
dataParams,
|
285
|
+
indexFilePath,
|
286
|
+
index,
|
287
|
+
fileName,
|
288
|
+
hash
|
289
|
+
) {
|
277
290
|
let retryCount = 0; // 当前重试次数
|
278
291
|
|
279
292
|
while (retryCount < maxRetries) {
|
@@ -281,24 +294,28 @@ async function postDataWithRetry(dataParams, indexFilePath, index) {
|
|
281
294
|
const resData = await postData(dataParams, indexFilePath);
|
282
295
|
if (resData.data.code === 200) {
|
283
296
|
logger("请求成功!");
|
284
|
-
logger(resData.data);
|
297
|
+
logger(resData.data.code);
|
298
|
+
// 文件名和索引值
|
299
|
+
successLogger(hash, index, fileName);
|
285
300
|
fs.rmdirSync(indexFilePath, { recursive: true });
|
286
|
-
return;
|
301
|
+
return;
|
287
302
|
} else if (resData.data.code === 300) {
|
288
303
|
// 重复上传,不捕获此错误
|
289
304
|
logger(`第${index}条文件-${index}重复上传!`);
|
290
305
|
fs.rmdirSync(indexFilePath, { recursive: true });
|
291
|
-
return;
|
306
|
+
return;
|
292
307
|
} else {
|
293
308
|
// 其他错误,抛出异常
|
294
|
-
throw new Error(
|
309
|
+
throw new Error(
|
310
|
+
"请求code!==200:" + resData.data.code + resData.data.msg
|
311
|
+
);
|
295
312
|
}
|
296
313
|
} catch (error) {
|
297
314
|
logger(`请求失败,重试中... (${retryCount + 1}/${maxRetries})`);
|
298
315
|
logger(error);
|
299
316
|
retryCount++;
|
300
317
|
// 延时等待一段时间后再进行重试
|
301
|
-
await new Promise((resolve) => setTimeout(resolve, 100)); // 等待1秒
|
318
|
+
await new Promise((resolve) => setTimeout(resolve, 100)); // 等待0.1秒
|
302
319
|
}
|
303
320
|
}
|
304
321
|
// 如果达到最大重试次数仍然失败,则抛出异常
|
@@ -308,7 +325,7 @@ async function postDataWithRetry(dataParams, indexFilePath, index) {
|
|
308
325
|
/**
|
309
326
|
* 任务
|
310
327
|
*/
|
311
|
-
const task = async (row, index) => {
|
328
|
+
const task = async (row, index, hash) => {
|
312
329
|
try {
|
313
330
|
logger(
|
314
331
|
"**************************" + row.fileName + "**************************"
|
@@ -316,12 +333,11 @@ const task = async (row, index) => {
|
|
316
333
|
// Excel的列名分别为: fileName title keyword
|
317
334
|
let fileName = row.fileName;
|
318
335
|
const title = row.title;
|
336
|
+
const keyword = row.keyword;
|
319
337
|
// const keywordArr = row.keyword.split(",");
|
320
338
|
// const filteredArray = keywordArr.filter((item) => item.trim() !== "");
|
321
339
|
// const keyword = filteredArray.join(" ");
|
322
340
|
|
323
|
-
const keyword = row.keyword;
|
324
|
-
|
325
341
|
if (!fileName.includes(".")) {
|
326
342
|
fileName = row.fileName + ".mp3";
|
327
343
|
}
|
@@ -351,7 +367,6 @@ const task = async (row, index) => {
|
|
351
367
|
//index文件夹 output/0
|
352
368
|
const indexFilePath = path.join(workDir, "output", index + "");
|
353
369
|
|
354
|
-
const workStartTime = new Date();
|
355
370
|
await fs_asnyc.access(originFilePath, fs_asnyc.constants.F_OK);
|
356
371
|
logFileSize(originFilePath);
|
357
372
|
const dataParams = await getMetadata(
|
@@ -371,14 +386,9 @@ const task = async (row, index) => {
|
|
371
386
|
dataParams.duration
|
372
387
|
);
|
373
388
|
await archiveZip(fileName, indexFilePath, originFilePath);
|
374
|
-
const workEndTime = new Date();
|
375
|
-
const timeInSeconds = ((workEndTime - workStartTime) / 1000).toFixed(2);
|
376
|
-
|
377
|
-
logger(`第${index}条4090处理总时间:${timeInSeconds}秒`);
|
378
|
-
logger(`-------------------${new Date()}------------------`);
|
379
389
|
|
380
390
|
// 重试机制
|
381
|
-
await postDataWithRetry(dataParams, indexFilePath, index);
|
391
|
+
await postDataWithRetry(dataParams, indexFilePath, index, fileName, hash);
|
382
392
|
|
383
393
|
logger(
|
384
394
|
`----------------------------------------第${index}条结束---------------------------------end`
|
@@ -388,55 +398,92 @@ const task = async (row, index) => {
|
|
388
398
|
if (error.code === "ENOENT") {
|
389
399
|
logger(`音频文件 ${fileName} 不存在`);
|
390
400
|
} else {
|
391
|
-
logger("
|
401
|
+
logger("音频任务失败(最外层catch):" + error);
|
392
402
|
}
|
393
403
|
fs.rmdirSync(indexFilePath, { recursive: true });
|
394
|
-
disposeError(fileName);
|
404
|
+
disposeError(hash, { fileName, keyword, title });
|
395
405
|
|
396
406
|
//失败的时候,复制文件到错误文件夹中
|
397
|
-
const failPath = path.join(workDir, Error_Files_Dir, fileName);
|
398
|
-
moveFailFiles(originFilePath, failPath);
|
407
|
+
// const failPath = path.join(workDir, Error_Files_Dir, fileName);
|
408
|
+
// moveFailFiles(originFilePath, failPath);
|
409
|
+
}
|
410
|
+
};
|
411
|
+
|
412
|
+
const run = (index, data, hash) => {
|
413
|
+
try {
|
414
|
+
logger(
|
415
|
+
`run-------------------------------------第${index}条开始------------------------------------`
|
416
|
+
);
|
417
|
+
const row = data[index];
|
418
|
+
|
419
|
+
if (!row) {
|
420
|
+
taskIndex = 0;
|
421
|
+
logger("当前任务,最后一条已结束!");
|
422
|
+
|
423
|
+
// 是否存在错误列表? 存在的话,继续遍历
|
424
|
+
const errorExcelPath = path.join(workDir, `error${hash}.xlsx`);
|
425
|
+
if (isExist(errorExcelPath)) {
|
426
|
+
const jsonData2 = readExcel(errorExcelPath);
|
427
|
+
queue(taskIndex, jsonData2, hash);
|
428
|
+
} else {
|
429
|
+
logger("跑干了!");
|
430
|
+
}
|
431
|
+
|
432
|
+
return;
|
433
|
+
}
|
434
|
+
|
435
|
+
task(row, index)
|
436
|
+
.then(() => {
|
437
|
+
taskIndex++;
|
438
|
+
run(taskIndex, data, hash);
|
439
|
+
})
|
440
|
+
.catch((err) => {
|
441
|
+
throw new Error("task失败:" + err);
|
442
|
+
});
|
443
|
+
} catch (error) {
|
444
|
+
logger("捕获错误!" + error);
|
445
|
+
taskIndex++;
|
446
|
+
run(taskIndex, data, hash);
|
447
|
+
}
|
448
|
+
};
|
449
|
+
|
450
|
+
const queue = (taskIndex, jsonData, hash) => {
|
451
|
+
for (let i = 0; i < queueCount; i++) {
|
452
|
+
run(i + taskIndex, jsonData, hash);
|
399
453
|
}
|
400
454
|
};
|
401
455
|
|
402
456
|
const main = () => {
|
403
457
|
//当前任务hash
|
404
|
-
|
405
|
-
|
458
|
+
let hash = "";
|
459
|
+
let jsonData = [];
|
406
460
|
logger("音频批量任务任务开始---" + hash);
|
407
|
-
logger("当前目录: " + workDir + "
|
461
|
+
logger("当前目录: " + workDir + ";工作目录: " + exeDir);
|
408
462
|
|
409
|
-
|
463
|
+
// 读取success.txt,判断是否是 异常中断,
|
464
|
+
// 并根据success日志获取最后一行的hash,找到对应的error_hash_excel
|
410
465
|
|
411
|
-
const
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
const row = jsonData[index];
|
466
|
+
const successPath = path.join(workDir, "success.txt");
|
467
|
+
if (isExist(successPath)) {
|
468
|
+
const { loghash, lastItemIndex } = readTxt(successPath);
|
469
|
+
const errorExcelPath = path.join(workDir, `error${loghash}.xlsx`);
|
470
|
+
logger("成功日志存在,异常中断或者跑完了。");
|
417
471
|
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
})
|
427
|
-
.catch(() => {
|
428
|
-
taskIndex++;
|
429
|
-
run(taskIndex);
|
430
|
-
});
|
431
|
-
} catch (error) {
|
432
|
-
logger("捕获错误!" + error);
|
433
|
-
taskIndex++;
|
434
|
-
run(taskIndex);
|
472
|
+
hash = loghash;
|
473
|
+
taskIndex = lastItemIndex + 1; // lastItemIndex为最后一项,所有要+1
|
474
|
+
|
475
|
+
if (isExist(errorExcelPath)) {
|
476
|
+
jsonData = readExcel(errorExcelPath); // 数据来源于error excel
|
477
|
+
queue(taskIndex, jsonData, hash);
|
478
|
+
} else {
|
479
|
+
logger("跑干了!");
|
435
480
|
}
|
436
|
-
}
|
481
|
+
} else {
|
482
|
+
hash = generateUniqueHash().slice(0, 8);
|
483
|
+
logger("成功日志不存在,开始新任务");
|
437
484
|
|
438
|
-
|
439
|
-
|
485
|
+
jsonData = readExcel(excelDir);
|
486
|
+
queue(taskIndex, jsonData, hash);
|
440
487
|
}
|
441
488
|
};
|
442
489
|
|
package/utils/logger.js
CHANGED
@@ -13,17 +13,53 @@ const logger = (log) => {
|
|
13
13
|
});
|
14
14
|
};
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
);
|
22
|
-
fs.writeFileSync("
|
16
|
+
/**
|
17
|
+
* 成功日志
|
18
|
+
* @param {*} 日志内容 hash index fileName
|
19
|
+
*/
|
20
|
+
const successLogger = (hash, index, fileName) => {
|
21
|
+
console.log(log);
|
22
|
+
fs.writeFileSync("success.txt", hash + " " + index + " " + fileName + "\n", {
|
23
23
|
flag: "a",
|
24
24
|
});
|
25
25
|
};
|
26
26
|
|
27
|
+
//错误日志- xlsx
|
28
|
+
const disposeError = (hash, { fileName, keyword, title }) => {
|
29
|
+
// 构建 Excel 数据
|
30
|
+
const data = [[fileName, keyword, title]]; // 不包含表头
|
31
|
+
|
32
|
+
// 读取已存在的 Excel 文件
|
33
|
+
let existingData = [];
|
34
|
+
let existingWb;
|
35
|
+
try {
|
36
|
+
existingWb = XLSX.readFile(`error${hash}.xlsx`);
|
37
|
+
existingData = XLSX.utils.sheet_to_json(
|
38
|
+
existingWb.Sheets[existingWb.SheetNames[0]],
|
39
|
+
{ header: 1 }
|
40
|
+
);
|
41
|
+
} catch (error) {
|
42
|
+
logger("No existing file found, creating new one.");
|
43
|
+
// 如果文件不存在,添加表头
|
44
|
+
existingData.push(["fileName", "keyword", "title"]);
|
45
|
+
}
|
46
|
+
|
47
|
+
// 合并已有数据和新数据
|
48
|
+
const combinedData = existingData.concat(data);
|
49
|
+
|
50
|
+
// 创建新的 sheet
|
51
|
+
const newWs = XLSX.utils.aoa_to_sheet(combinedData);
|
52
|
+
|
53
|
+
// 创建新的 workbook
|
54
|
+
const wb = XLSX.utils.book_new();
|
55
|
+
|
56
|
+
// 将新的 sheet 添加到 workbook
|
57
|
+
XLSX.utils.book_append_sheet(wb, newWs, "Error Details");
|
58
|
+
|
59
|
+
// 保存 Excel 文件
|
60
|
+
XLSX.writeFile(wb, `error${hash}.xlsx`);
|
61
|
+
};
|
62
|
+
|
27
63
|
/**
|
28
64
|
* 读取Excel
|
29
65
|
* @param {*} path Excel路径
|
@@ -45,4 +81,5 @@ module.exports = {
|
|
45
81
|
readExcel,
|
46
82
|
logger,
|
47
83
|
disposeError,
|
84
|
+
successLogger,
|
48
85
|
};
|
package/utils/settleFiles.js
CHANGED
@@ -40,6 +40,19 @@ function ensureDirSync(dirpath) {
|
|
40
40
|
}
|
41
41
|
}
|
42
42
|
|
43
|
+
/**
|
44
|
+
* 判断文件是否存在
|
45
|
+
*/
|
46
|
+
function isExist(filePath) {
|
47
|
+
fs.access(filePath, fs.constants.F_OK, (err) => {
|
48
|
+
if (err) {
|
49
|
+
return false;
|
50
|
+
} else {
|
51
|
+
return true;
|
52
|
+
}
|
53
|
+
});
|
54
|
+
}
|
55
|
+
|
43
56
|
/**
|
44
57
|
* 上传失败后,存入新文件夹(手动创建)
|
45
58
|
*/
|
@@ -50,9 +63,27 @@ const moveFailFiles = (originFilePath, failPath) => {
|
|
50
63
|
}
|
51
64
|
};
|
52
65
|
|
66
|
+
//数组 item为:hash index fileName
|
67
|
+
function readTxt(path) {
|
68
|
+
try {
|
69
|
+
const data = fs.readFileSync(path, "utf-8");
|
70
|
+
const arr = data.split("\n").map((line) => line.trim()); // 删除每行两侧的空白符
|
71
|
+
const lastItem = arr[arr.length - 1];
|
72
|
+
|
73
|
+
const loghash = lastItem.split(" ")[0];
|
74
|
+
const lastItemIndex = lastItem.split(" ")[1];
|
75
|
+
return { loghash, lastItemIndex };
|
76
|
+
} catch (error) {
|
77
|
+
console.error("readErrorTxt函数出错:", error);
|
78
|
+
return {};
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
53
82
|
module.exports = {
|
54
83
|
findFileInDir,
|
55
84
|
logFileSize,
|
56
85
|
ensureDirSync,
|
57
86
|
moveFailFiles,
|
87
|
+
isExist,
|
88
|
+
readTxt,
|
58
89
|
};
|