tools_batch_files 1.0.21 → 1.0.22
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/index.js +23 -13
- package/package.json +1 -1
- package/src/photoBatch.js +524 -536
- package/src/photoBatchBack.js +0 -3
package/index.js
CHANGED
@@ -30,10 +30,10 @@ const SOURCE_VIDEO_DIR = "source_video";
|
|
30
30
|
const ZIP_FILES_DIR = "zip";
|
31
31
|
|
32
32
|
//并发数量
|
33
|
-
const queueCount =
|
33
|
+
const queueCount = 50;
|
34
34
|
|
35
35
|
//起始任务下标
|
36
|
-
let taskIndex =
|
36
|
+
let taskIndex = 2066;
|
37
37
|
|
38
38
|
/**
|
39
39
|
* 递归遍历文件夹,查找mp4文件
|
@@ -102,12 +102,12 @@ const logger = (log, hash, err) => {
|
|
102
102
|
};
|
103
103
|
|
104
104
|
//错误日志
|
105
|
-
const disposeError = (
|
106
|
-
logger("---任务失败---"
|
105
|
+
const disposeError = (fileName) => {
|
106
|
+
logger("---任务失败---" + fileName);
|
107
107
|
logger(
|
108
108
|
`******************************************************************end`
|
109
109
|
);
|
110
|
-
fs.writeFileSync("error.txt",
|
110
|
+
fs.writeFileSync("error.txt", fileName + "\n", {
|
111
111
|
flag: "a",
|
112
112
|
});
|
113
113
|
};
|
@@ -422,7 +422,7 @@ const getMetadata = async (
|
|
422
422
|
video_id: rowFileName,
|
423
423
|
title,
|
424
424
|
keyword,
|
425
|
-
pr:
|
425
|
+
pr: 100,
|
426
426
|
format: "mp4",
|
427
427
|
category_id: 4,
|
428
428
|
demand_kind: 23,
|
@@ -485,10 +485,11 @@ const postData = (dataParams, indexFilePath) => {
|
|
485
485
|
|
486
486
|
logger("等待接口返回结果……");
|
487
487
|
|
488
|
-
return axios.post("http://
|
488
|
+
return axios.post("http://127.0.0.1:9999/upload/video", formData, {
|
489
489
|
headers: {
|
490
490
|
"Content-Type": "multipart/form-data",
|
491
491
|
},
|
492
|
+
timeout: 600000,
|
492
493
|
});
|
493
494
|
};
|
494
495
|
|
@@ -509,7 +510,7 @@ const task = async (row, index) => {
|
|
509
510
|
const keyword = filteredArray.join(" ");
|
510
511
|
|
511
512
|
if (!fileName.includes(".")) {
|
512
|
-
fileName = row.fileName + ".
|
513
|
+
fileName = row.fileName + ".mov";
|
513
514
|
}
|
514
515
|
|
515
516
|
// 源视频文件路径
|
@@ -519,7 +520,7 @@ const task = async (row, index) => {
|
|
519
520
|
);
|
520
521
|
|
521
522
|
if (!originFilePath) {
|
522
|
-
logger(
|
523
|
+
logger(`视频文件 ${fileName} 不存在`);
|
523
524
|
return;
|
524
525
|
}
|
525
526
|
logger("源视频文件路径");
|
@@ -547,10 +548,17 @@ const task = async (row, index) => {
|
|
547
548
|
keyword,
|
548
549
|
}
|
549
550
|
);
|
550
|
-
console.log("dataParams参数");
|
551
|
-
console.log(dataParams);
|
552
551
|
|
553
552
|
const resData = await postData(dataParams, indexFilePath);
|
553
|
+
if (resData.data.code === 200) {
|
554
|
+
logger("请求成功!");
|
555
|
+
logger(resData.data.code);
|
556
|
+
logger(resData.data);
|
557
|
+
//删除文件夹
|
558
|
+
// fs.rmdirSync(indexFilePath, { recursive: true });
|
559
|
+
} else {
|
560
|
+
throw new Error("请求失败!" + resData.data.msg);
|
561
|
+
}
|
554
562
|
logger(resData.data);
|
555
563
|
logger(
|
556
564
|
`----------------------------------------第${index}条结束---------------------------------end`
|
@@ -563,7 +571,9 @@ const task = async (row, index) => {
|
|
563
571
|
logger("视频处理失败:");
|
564
572
|
logger(error);
|
565
573
|
}
|
566
|
-
|
574
|
+
logger("catch日志*********************************");
|
575
|
+
disposeError(fileName);
|
576
|
+
// fs.rmdirSync(indexFilePath, { recursive: true });
|
567
577
|
}
|
568
578
|
};
|
569
579
|
|
@@ -601,7 +611,7 @@ const transitionExcelToJSON = () => {
|
|
601
611
|
};
|
602
612
|
|
603
613
|
for (let i = 0; i < queueCount; i++) {
|
604
|
-
run(i);
|
614
|
+
run(i + taskIndex);
|
605
615
|
}
|
606
616
|
};
|
607
617
|
|
package/package.json
CHANGED
package/src/photoBatch.js
CHANGED
@@ -1,536 +1,524 @@
|
|
1
|
-
#!/usr/bin/env node
|
2
|
-
const XLSX = require("xlsx");
|
3
|
-
const ffmpeg = require("fluent-ffmpeg");
|
4
|
-
const fs = require("fs");
|
5
|
-
const path = require("path");
|
6
|
-
const fs_asnyc = require("fs").promises;
|
7
|
-
const archiver = require("archiver");
|
8
|
-
const axios = require("axios");
|
9
|
-
const generateUniqueHash = require("../utils/index");
|
10
|
-
const FormData = require("form-data");
|
11
|
-
|
12
|
-
//执行目录
|
13
|
-
const exeDir = __dirname;
|
14
|
-
//当前工作目录
|
15
|
-
const workDir = process.cwd();
|
16
|
-
|
17
|
-
// 表格目录
|
18
|
-
const excelDir = path.join(workDir, "excel", "excel.xlsx");
|
19
|
-
//水印
|
20
|
-
const watermarkImage = path.join(__dirname, "..", "imgs", "picWater.png");
|
21
|
-
|
22
|
-
// 截图数量
|
23
|
-
const SCREENSHOT_COUNT = 5;
|
24
|
-
const ORIGIN_FILE_DIR = "photos";
|
25
|
-
const PHOTO_PREVIEW_DIR = "preview_photo";
|
26
|
-
const ZIP_VIDEO_DIR = "zip_video";
|
27
|
-
const ZIP_VIDEO_DIR_400 = "small_video";
|
28
|
-
const SCREENSHOT_DIR = "preview_photo";
|
29
|
-
const SCREENSHOT_WATERMARK_DIR = "screenshots_watermark";
|
30
|
-
const ZIP_WATERMARK_VIDEO_DIR = "zip_watermark_video";
|
31
|
-
const ZIP_SCREENSHOT_WM_DIR = "preview_watermark_photo";
|
32
|
-
const SOURCE_PHOTO_DIR = "source_photo";
|
33
|
-
const ZIP_FILES_DIR = "zip";
|
34
|
-
|
35
|
-
const expandedName = ".jpg";
|
36
|
-
|
37
|
-
//并发数量
|
38
|
-
const queueCount = 50;
|
39
|
-
|
40
|
-
//起始任务下标
|
41
|
-
let taskIndex =
|
42
|
-
|
43
|
-
const readExcel = (path) => {
|
44
|
-
const workbook = XLSX.readFile(path);
|
45
|
-
|
46
|
-
// 获取第一个工作表(Sheet)
|
47
|
-
const firstSheetName = workbook.SheetNames[0];
|
48
|
-
const worksheet = workbook.Sheets[firstSheetName];
|
49
|
-
|
50
|
-
// 将工作表转换为 JSON 对象
|
51
|
-
const jsonData = XLSX.utils.sheet_to_json(worksheet);
|
52
|
-
return jsonData;
|
53
|
-
};
|
54
|
-
|
55
|
-
function logFileSize(path) {
|
56
|
-
const fileSize = fs.statSync(path).size / (1024 * 1024);
|
57
|
-
const formattedSize = fileSize.toFixed(2); // 保留两位小数
|
58
|
-
logger(`图片大小:${formattedSize}M`);
|
59
|
-
}
|
60
|
-
|
61
|
-
//普通日志
|
62
|
-
const logger = (log, hash, err) => {
|
63
|
-
console.log(log);
|
64
|
-
fs.writeFileSync("log.txt", log + "\n", {
|
65
|
-
flag: "a",
|
66
|
-
});
|
67
|
-
};
|
68
|
-
|
69
|
-
//错误日志
|
70
|
-
const disposeError = (err) => {
|
71
|
-
logger("---任务失败---", err);
|
72
|
-
logger(
|
73
|
-
`******************************************************************end`
|
74
|
-
);
|
75
|
-
fs.writeFileSync("error.txt", err + "\n", {
|
76
|
-
flag: "a",
|
77
|
-
});
|
78
|
-
};
|
79
|
-
|
80
|
-
/**
|
81
|
-
* 递归遍历文件夹,查找文件
|
82
|
-
* @param {*} dir 文件夹路径
|
83
|
-
* @param {*} fileName 文件名称
|
84
|
-
* @returns string 匹配成功的文件路径
|
85
|
-
*/
|
86
|
-
function findFileInDir(dir, fileName) {
|
87
|
-
const files = fs.readdirSync(dir);
|
88
|
-
for (const file of files) {
|
89
|
-
const filePath = path.join(dir, file);
|
90
|
-
const stat = fs.statSync(filePath);
|
91
|
-
if (stat.isDirectory()) {
|
92
|
-
const result = findFileInDir(filePath, fileName);
|
93
|
-
if (result) {
|
94
|
-
return result;
|
95
|
-
}
|
96
|
-
} else if (file.startsWith(fileName) && file.endsWith(expandedName)) {
|
97
|
-
return filePath;
|
98
|
-
}
|
99
|
-
}
|
100
|
-
return null;
|
101
|
-
}
|
102
|
-
|
103
|
-
// function findFileInDir(dir, fileName) {
|
104
|
-
// return new Promise((resolve, reject) => {
|
105
|
-
// fs.readdir(dir, (err, files) => {
|
106
|
-
// if (err) {
|
107
|
-
// reject(err);
|
108
|
-
// return;
|
109
|
-
// }
|
110
|
-
|
111
|
-
// // 遍历目录中的文件和子目录
|
112
|
-
// for (const file of files) {
|
113
|
-
// const filePath = path.join(dir, file);
|
114
|
-
// fs.stat(filePath, (err, stat) => {
|
115
|
-
// if (err) {
|
116
|
-
// reject(err); // 如果获取文件状态出错,直接reject
|
117
|
-
// return;
|
118
|
-
// }
|
119
|
-
// if (stat.isDirectory()) {
|
120
|
-
// // 如果是目录,递归调用findFileInDir
|
121
|
-
// findFileInDir(filePath, fileName)
|
122
|
-
// .then(resolve) // 如果找到了目标文件,将结果resolve
|
123
|
-
// .catch(reject); // 如果在子目录中出错,将错误reject
|
124
|
-
// } else if (file.startsWith(fileName) && file.endsWith(expandedName)) {
|
125
|
-
// resolve(filePath); // 如果找到了目标文件,将结果resolve
|
126
|
-
// }
|
127
|
-
// });
|
128
|
-
// }
|
129
|
-
|
130
|
-
// // 如果遍历完了所有文件和子目录仍未找到目标文件,resolve一个null表示未找到
|
131
|
-
// resolve(null);
|
132
|
-
// });
|
133
|
-
// });
|
134
|
-
// }
|
135
|
-
|
136
|
-
/**
|
137
|
-
* 生成预览图 indexFilePath: output/0
|
138
|
-
* originFilePath E:\workspace\图片测试\photos\abc222.png
|
139
|
-
*/
|
140
|
-
const PriviewPhoto = (indexFilePath, originFilePath, fileName) => {
|
141
|
-
//存放预览图图的文件夹
|
142
|
-
const outputDir = path.join(indexFilePath, SCREENSHOT_DIR);
|
143
|
-
ensureDirSync(outputDir);
|
144
|
-
|
145
|
-
const outputFile = path.join(outputDir, fileName);
|
146
|
-
|
147
|
-
return new Promise((resolve, reject) => {
|
148
|
-
const watermarkScreenshotsComand = ffmpeg(originFilePath);
|
149
|
-
watermarkScreenshotsComand
|
150
|
-
.size("1280x?")
|
151
|
-
.output(outputFile)
|
152
|
-
.on("error", (err) => {
|
153
|
-
logger("截图预览图出错: " + err);
|
154
|
-
reject();
|
155
|
-
})
|
156
|
-
.on("end", () => {
|
157
|
-
logger("预览图完成: " + outputFile);
|
158
|
-
resolve();
|
159
|
-
})
|
160
|
-
.run();
|
161
|
-
});
|
162
|
-
};
|
163
|
-
|
164
|
-
/**
|
165
|
-
* 生成水印预览图
|
166
|
-
*/
|
167
|
-
const watermarkPriviewPhoto = (indexFilePath, originFilePath, fileName) => {
|
168
|
-
//存放水印截图的文件夹
|
169
|
-
const outputDir = path.join(indexFilePath, ZIP_SCREENSHOT_WM_DIR);
|
170
|
-
const inputDir = path.join(indexFilePath, SCREENSHOT_DIR, fileName);
|
171
|
-
ensureDirSync(outputDir);
|
172
|
-
|
173
|
-
const outputFile = path.join(outputDir, fileName);
|
174
|
-
|
175
|
-
return new Promise((resolve, reject) => {
|
176
|
-
const watermarkScreenshotsComand = ffmpeg(inputDir);
|
177
|
-
watermarkScreenshotsComand
|
178
|
-
.input(watermarkImage)
|
179
|
-
.complexFilter("overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2")
|
180
|
-
.output(outputFile)
|
181
|
-
.on("error", (err) => {
|
182
|
-
logger("截图添加水印出错: " + err);
|
183
|
-
reject();
|
184
|
-
})
|
185
|
-
.on("end", () => {
|
186
|
-
logger("截图水印添加完成: " + outputFile);
|
187
|
-
resolve();
|
188
|
-
})
|
189
|
-
.run();
|
190
|
-
});
|
191
|
-
};
|
192
|
-
|
193
|
-
/**
|
194
|
-
* 确保目录存在,如果不存在则创建它
|
195
|
-
*/
|
196
|
-
function ensureDirSync(dirpath) {
|
197
|
-
try {
|
198
|
-
if (!fs.existsSync(dirpath)) {
|
199
|
-
fs.mkdirSync(dirpath, { recursive: true });
|
200
|
-
logger(`目录创建成功:${dirpath}`);
|
201
|
-
}
|
202
|
-
} catch (err) {
|
203
|
-
logger(`创建目录时出错:${err}`);
|
204
|
-
throw err;
|
205
|
-
}
|
206
|
-
}
|
207
|
-
|
208
|
-
/**
|
209
|
-
* 打包物料
|
210
|
-
*/
|
211
|
-
const archiveZip = (fileName, inputPath, originFilePath) => {
|
212
|
-
const zipDir = path.join(inputPath, "zip");
|
213
|
-
const timestamp = new Date().getTime();
|
214
|
-
|
215
|
-
ensureDirSync(zipDir);
|
216
|
-
const zipStream = fs.createWriteStream(
|
217
|
-
path.join(zipDir, `package${timestamp}.zip`)
|
218
|
-
);
|
219
|
-
const archive = archiver("zip", {
|
220
|
-
zlib: { level: 9 },
|
221
|
-
});
|
222
|
-
|
223
|
-
return new Promise((resolve, reject) => {
|
224
|
-
zipStream.on("close", function () {
|
225
|
-
logger("压缩数据:" + archive.pointer() + " total bytes");
|
226
|
-
logger(
|
227
|
-
"完成归档archiver has been finalized and the output file descriptor has closed."
|
228
|
-
);
|
229
|
-
resolve();
|
230
|
-
});
|
231
|
-
|
232
|
-
archive.on("warning", function (err) {
|
233
|
-
if (err.code === "ENOENT") {
|
234
|
-
logger("压缩-warning:" + err);
|
235
|
-
} else {
|
236
|
-
throw err;
|
237
|
-
}
|
238
|
-
});
|
239
|
-
|
240
|
-
archive.on("error", function (err) {
|
241
|
-
logger("压缩失败!" + err);
|
242
|
-
reject();
|
243
|
-
});
|
244
|
-
|
245
|
-
archive.pipe(zipStream);
|
246
|
-
const directories = [ZIP_SCREENSHOT_WM_DIR, SCREENSHOT_DIR];
|
247
|
-
|
248
|
-
directories.forEach((dir) => {
|
249
|
-
const dirPath = path.join(inputPath, dir);
|
250
|
-
archive.directory(dirPath, dir);
|
251
|
-
});
|
252
|
-
|
253
|
-
archive.file(originFilePath, {
|
254
|
-
name: path.join(SOURCE_PHOTO_DIR, fileName),
|
255
|
-
});
|
256
|
-
// 完成归档
|
257
|
-
archive.finalize();
|
258
|
-
});
|
259
|
-
};
|
260
|
-
|
261
|
-
/**
|
262
|
-
* 获取 元数据
|
263
|
-
*/
|
264
|
-
const getMetadata = async (
|
265
|
-
fileName,
|
266
|
-
indexFilePath,
|
267
|
-
originFilePath,
|
268
|
-
{ rowFileName, title, keyword }
|
269
|
-
) => {
|
270
|
-
//源图片数据
|
271
|
-
const photoMetadataComand = ffmpeg(originFilePath);
|
272
|
-
//预览图数据
|
273
|
-
const photoInputPath = path.join(indexFilePath, SCREENSHOT_DIR, fileName);
|
274
|
-
const photoPreviewMetadataComand = ffmpeg(photoInputPath);
|
275
|
-
|
276
|
-
const metaDataParams = {
|
277
|
-
photo_id: rowFileName,
|
278
|
-
width: "",
|
279
|
-
height: "",
|
280
|
-
format: "",
|
281
|
-
size: "",
|
282
|
-
pr: 160,
|
283
|
-
dpi: 0,
|
284
|
-
is_government: 0,
|
285
|
-
common_width: "",
|
286
|
-
common_height: "",
|
287
|
-
dujia: 0,
|
288
|
-
xiaoxiang: 0,
|
289
|
-
title,
|
290
|
-
keyword,
|
291
|
-
en_keyword: "",
|
292
|
-
// preview_path: "",
|
293
|
-
// markImage_path: "",
|
294
|
-
// photo_path: "",
|
295
|
-
// common_image_path: "",
|
296
|
-
// en_keyword: "",
|
297
|
-
plate_id: 3,
|
298
|
-
transform_plate_id: 3,
|
299
|
-
tag_id: 47,
|
300
|
-
userid: 1003,
|
301
|
-
username: "美好景象",
|
302
|
-
demand_kind: 3,
|
303
|
-
source_from: 71,
|
304
|
-
file: "",
|
305
|
-
};
|
306
|
-
|
307
|
-
await new Promise((resolve, reject) => {
|
308
|
-
photoMetadataComand.ffprobe(function (err, metadata) {
|
309
|
-
// console.log("metadata");
|
310
|
-
// console.log(JSON.stringify(metadata));
|
311
|
-
if (metadata) {
|
312
|
-
const formatStream = metadata.format;
|
313
|
-
const photoStream = metadata.streams.find(
|
314
|
-
(s) => s.codec_type === "video"
|
315
|
-
);
|
316
|
-
|
317
|
-
metaDataParams.width = photoStream.width;
|
318
|
-
metaDataParams.height = photoStream.height;
|
319
|
-
// metaDataParams.format = formatStream.format_name;
|
320
|
-
metaDataParams.format = "jpg";
|
321
|
-
metaDataParams.size = formatStream.size;
|
322
|
-
|
323
|
-
resolve();
|
324
|
-
} else {
|
325
|
-
reject(err);
|
326
|
-
}
|
327
|
-
});
|
328
|
-
});
|
329
|
-
await new Promise((resolve, reject) => {
|
330
|
-
photoPreviewMetadataComand.ffprobe(function (err, metadata) {
|
331
|
-
if (metadata) {
|
332
|
-
const photoStream = metadata.streams.find(
|
333
|
-
(s) => s.codec_type === "video"
|
334
|
-
);
|
335
|
-
|
336
|
-
metaDataParams.common_width = photoStream.width;
|
337
|
-
metaDataParams.common_height = photoStream.height;
|
338
|
-
resolve();
|
339
|
-
} else {
|
340
|
-
reject(err);
|
341
|
-
}
|
342
|
-
});
|
343
|
-
});
|
344
|
-
|
345
|
-
return metaDataParams;
|
346
|
-
};
|
347
|
-
|
348
|
-
/**
|
349
|
-
* 接口
|
350
|
-
*/
|
351
|
-
const postData = (dataParams, indexFilePath) => {
|
352
|
-
const formData = new FormData();
|
353
|
-
|
354
|
-
const zipFiles = fs
|
355
|
-
.readdirSync(path.join(indexFilePath, ZIP_FILES_DIR))
|
356
|
-
.find((file) => file.endsWith(".zip"));
|
357
|
-
|
358
|
-
const packageZip = path.join(indexFilePath, ZIP_FILES_DIR, zipFiles);
|
359
|
-
|
360
|
-
formData.append("file", fs.createReadStream(packageZip));
|
361
|
-
for (const key in dataParams) {
|
362
|
-
if (Object.hasOwnProperty.call(dataParams, key)) {
|
363
|
-
const value = dataParams[key];
|
364
|
-
formData.append(key, value);
|
365
|
-
}
|
366
|
-
}
|
367
|
-
|
368
|
-
logger("等待接口返回结果……");
|
369
|
-
|
370
|
-
// return axios.post("http://192.168.102.61:9999/upload/photo", formData, {
|
371
|
-
return axios.post("http://127.0.0.1:9999/upload/photo", formData, {
|
372
|
-
headers: {
|
373
|
-
"Content-Type": "multipart/form-data",
|
374
|
-
},
|
375
|
-
timeout: 300000,
|
376
|
-
});
|
377
|
-
};
|
378
|
-
|
379
|
-
/**
|
380
|
-
* 任务
|
381
|
-
*/
|
382
|
-
const task = async (row, index) => {
|
383
|
-
logger(
|
384
|
-
"**************************" + row.fileName + "**************************"
|
385
|
-
);
|
386
|
-
// Excel的列名分别为: fileName title keyword
|
387
|
-
// 表格中文件名无后缀,遂手动添加写死为mp4
|
388
|
-
let fileName = row.fileName;
|
389
|
-
const rowFileName = row.fileName;
|
390
|
-
const title = row.title;
|
391
|
-
const keywordArr = row.keyword.split(",");
|
392
|
-
const filteredArray = keywordArr.filter((item) => item.trim() !== "");
|
393
|
-
const keyword = filteredArray.join(" ");
|
394
|
-
|
395
|
-
if (!fileName.includes(".")) {
|
396
|
-
fileName = row.fileName + expandedName;
|
397
|
-
}
|
398
|
-
|
399
|
-
const getPathStartTime = new Date();
|
400
|
-
// 源图片文件夹路径
|
401
|
-
const originFilePath = await findFileInDir(
|
402
|
-
path.join(workDir, ORIGIN_FILE_DIR),
|
403
|
-
fileName
|
404
|
-
);
|
405
|
-
const getPathEndTime = new Date();
|
406
|
-
const timeInSeconds = ((getPathEndTime - getPathStartTime) / 1000).toFixed(2);
|
407
|
-
|
408
|
-
logger(`第${index}条Path路径搜索时间:${timeInSeconds}秒`);
|
409
|
-
logger(`-------------------${new Date()}------------------`);
|
410
|
-
|
411
|
-
console.log("originFilePath:" + originFilePath);
|
412
|
-
console.log("fileName:" + fileName);
|
413
|
-
|
414
|
-
if (!originFilePath) {
|
415
|
-
logger(`图片文件 ${fileName} 不存在`);
|
416
|
-
return;
|
417
|
-
}
|
418
|
-
|
419
|
-
//index文件夹 output/0
|
420
|
-
const indexFilePath = path.join(workDir, "output", index + "");
|
421
|
-
|
422
|
-
try {
|
423
|
-
const workStartTime = new Date();
|
424
|
-
await fs_asnyc.access(originFilePath, fs_asnyc.constants.F_OK);
|
425
|
-
logFileSize(originFilePath);
|
426
|
-
await PriviewPhoto(indexFilePath, originFilePath, fileName);
|
427
|
-
await watermarkPriviewPhoto(indexFilePath, originFilePath, fileName);
|
428
|
-
await archiveZip(fileName, indexFilePath, originFilePath);
|
429
|
-
const dataParams = await getMetadata(
|
430
|
-
fileName,
|
431
|
-
indexFilePath,
|
432
|
-
originFilePath,
|
433
|
-
{
|
434
|
-
rowFileName,
|
435
|
-
title,
|
436
|
-
keyword,
|
437
|
-
}
|
438
|
-
);
|
439
|
-
const workEndTime = new Date();
|
440
|
-
const timeInSeconds = ((workEndTime - workStartTime) / 1000).toFixed(2);
|
441
|
-
|
442
|
-
logger(`第${index}条4090处理总时间:${timeInSeconds}秒`);
|
443
|
-
logger(`-------------------${new Date()}------------------`);
|
444
|
-
|
445
|
-
const postStartTime = new Date();
|
446
|
-
const resData = await postData(dataParams, indexFilePath);
|
447
|
-
const postEndTime = new Date();
|
448
|
-
const timeInSeconds1 = ((postEndTime - postStartTime) / 1000).toFixed(2);
|
449
|
-
|
450
|
-
logger(`第${index}条接口处理总时间:${timeInSeconds1}秒`);
|
451
|
-
logger(`-------------------${new Date()}------------------`);
|
452
|
-
|
453
|
-
if (resData.data.code === 200) {
|
454
|
-
logger("请求成功!");
|
455
|
-
logger(resData.data.code);
|
456
|
-
console.log(resData.data);
|
457
|
-
//删除文件夹
|
458
|
-
fs.rmdirSync(indexFilePath, { recursive: true });
|
459
|
-
} else {
|
460
|
-
throw new Error("请求失败!" + resData.data.msg);
|
461
|
-
}
|
462
|
-
|
463
|
-
logger(
|
464
|
-
`----------------------------------------第${index}条结束---------------------------------end`
|
465
|
-
);
|
466
|
-
} catch (error) {
|
467
|
-
// 可以约定code,来表示不同的错误信息
|
468
|
-
if (error.code === "ENOENT") {
|
469
|
-
logger(`图片文件 ${fileName} 不存在`);
|
470
|
-
} else {
|
471
|
-
logger("图片任务处理失败:" + error);
|
472
|
-
logger(error);
|
473
|
-
}
|
474
|
-
fs.rmdirSync(indexFilePath, { recursive: true });
|
475
|
-
disposeError(fileName);
|
476
|
-
}
|
477
|
-
};
|
478
|
-
|
479
|
-
/**
|
480
|
-
* 解析Excel数据
|
481
|
-
*/
|
482
|
-
const transitionExcelToJSON = () => {
|
483
|
-
//当前任务hash
|
484
|
-
const hashOrigin = generateUniqueHash();
|
485
|
-
const hash = hashOrigin.slice(0, 8);
|
486
|
-
logger("图片批量任务任务开始---" + hash);
|
487
|
-
logger("当前目录: " + workDir);
|
488
|
-
logger("工作目录: " + __dirname);
|
489
|
-
|
490
|
-
const jsonData = readExcel(excelDir);
|
491
|
-
|
492
|
-
const run = (index) => {
|
493
|
-
try {
|
494
|
-
logger(
|
495
|
-
`run-------------------------------------第${index}条开始------------------------------------`
|
496
|
-
);
|
497
|
-
|
498
|
-
const row = jsonData[index];
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
);
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
logger("捕获错误!" + error);
|
526
|
-
taskIndex++;
|
527
|
-
run(taskIndex);
|
528
|
-
}
|
529
|
-
};
|
530
|
-
|
531
|
-
for (let i = 0; i < queueCount; i++) {
|
532
|
-
run(i + taskIndex);
|
533
|
-
}
|
534
|
-
};
|
535
|
-
|
536
|
-
transitionExcelToJSON();
|
1
|
+
#!/usr/bin/env node
|
2
|
+
const XLSX = require("xlsx");
|
3
|
+
const ffmpeg = require("fluent-ffmpeg");
|
4
|
+
const fs = require("fs");
|
5
|
+
const path = require("path");
|
6
|
+
const fs_asnyc = require("fs").promises;
|
7
|
+
const archiver = require("archiver");
|
8
|
+
const axios = require("axios");
|
9
|
+
const generateUniqueHash = require("../utils/index");
|
10
|
+
const FormData = require("form-data");
|
11
|
+
|
12
|
+
//执行目录
|
13
|
+
const exeDir = __dirname;
|
14
|
+
//当前工作目录
|
15
|
+
const workDir = process.cwd();
|
16
|
+
|
17
|
+
// 表格目录
|
18
|
+
const excelDir = path.join(workDir, "excel", "excel.xlsx");
|
19
|
+
//水印
|
20
|
+
const watermarkImage = path.join(__dirname, "..", "imgs", "picWater.png");
|
21
|
+
|
22
|
+
// 截图数量
|
23
|
+
const SCREENSHOT_COUNT = 5;
|
24
|
+
const ORIGIN_FILE_DIR = "photos";
|
25
|
+
const PHOTO_PREVIEW_DIR = "preview_photo";
|
26
|
+
const ZIP_VIDEO_DIR = "zip_video";
|
27
|
+
const ZIP_VIDEO_DIR_400 = "small_video";
|
28
|
+
const SCREENSHOT_DIR = "preview_photo";
|
29
|
+
const SCREENSHOT_WATERMARK_DIR = "screenshots_watermark";
|
30
|
+
const ZIP_WATERMARK_VIDEO_DIR = "zip_watermark_video";
|
31
|
+
const ZIP_SCREENSHOT_WM_DIR = "preview_watermark_photo";
|
32
|
+
const SOURCE_PHOTO_DIR = "source_photo";
|
33
|
+
const ZIP_FILES_DIR = "zip";
|
34
|
+
|
35
|
+
const expandedName = ".jpg";
|
36
|
+
|
37
|
+
//并发数量
|
38
|
+
const queueCount = 50;
|
39
|
+
|
40
|
+
//起始任务下标
|
41
|
+
let taskIndex = 0;
|
42
|
+
|
43
|
+
const readExcel = (path) => {
|
44
|
+
const workbook = XLSX.readFile(path);
|
45
|
+
|
46
|
+
// 获取第一个工作表(Sheet)
|
47
|
+
const firstSheetName = workbook.SheetNames[0];
|
48
|
+
const worksheet = workbook.Sheets[firstSheetName];
|
49
|
+
|
50
|
+
// 将工作表转换为 JSON 对象
|
51
|
+
const jsonData = XLSX.utils.sheet_to_json(worksheet);
|
52
|
+
return jsonData;
|
53
|
+
};
|
54
|
+
|
55
|
+
function logFileSize(path) {
|
56
|
+
const fileSize = fs.statSync(path).size / (1024 * 1024);
|
57
|
+
const formattedSize = fileSize.toFixed(2); // 保留两位小数
|
58
|
+
logger(`图片大小:${formattedSize}M`);
|
59
|
+
}
|
60
|
+
|
61
|
+
//普通日志
|
62
|
+
const logger = (log, hash, err) => {
|
63
|
+
console.log(log);
|
64
|
+
fs.writeFileSync("log.txt", log + "\n", {
|
65
|
+
flag: "a",
|
66
|
+
});
|
67
|
+
};
|
68
|
+
|
69
|
+
//错误日志
|
70
|
+
const disposeError = (err) => {
|
71
|
+
logger("---任务失败---", err);
|
72
|
+
logger(
|
73
|
+
`******************************************************************end`
|
74
|
+
);
|
75
|
+
fs.writeFileSync("error.txt", err + "\n", {
|
76
|
+
flag: "a",
|
77
|
+
});
|
78
|
+
};
|
79
|
+
|
80
|
+
/**
|
81
|
+
* 递归遍历文件夹,查找文件
|
82
|
+
* @param {*} dir 文件夹路径
|
83
|
+
* @param {*} fileName 文件名称
|
84
|
+
* @returns string 匹配成功的文件路径
|
85
|
+
*/
|
86
|
+
function findFileInDir(dir, fileName) {
|
87
|
+
const files = fs.readdirSync(dir);
|
88
|
+
for (const file of files) {
|
89
|
+
const filePath = path.join(dir, file);
|
90
|
+
const stat = fs.statSync(filePath);
|
91
|
+
if (stat.isDirectory()) {
|
92
|
+
const result = findFileInDir(filePath, fileName);
|
93
|
+
if (result) {
|
94
|
+
return result;
|
95
|
+
}
|
96
|
+
} else if (file.startsWith(fileName) && file.endsWith(expandedName)) {
|
97
|
+
return filePath;
|
98
|
+
}
|
99
|
+
}
|
100
|
+
return null;
|
101
|
+
}
|
102
|
+
|
103
|
+
// function findFileInDir(dir, fileName) {
|
104
|
+
// return new Promise((resolve, reject) => {
|
105
|
+
// fs.readdir(dir, (err, files) => {
|
106
|
+
// if (err) {
|
107
|
+
// reject(err);
|
108
|
+
// return;
|
109
|
+
// }
|
110
|
+
|
111
|
+
// // 遍历目录中的文件和子目录
|
112
|
+
// for (const file of files) {
|
113
|
+
// const filePath = path.join(dir, file);
|
114
|
+
// fs.stat(filePath, (err, stat) => {
|
115
|
+
// if (err) {
|
116
|
+
// reject(err); // 如果获取文件状态出错,直接reject
|
117
|
+
// return;
|
118
|
+
// }
|
119
|
+
// if (stat.isDirectory()) {
|
120
|
+
// // 如果是目录,递归调用findFileInDir
|
121
|
+
// findFileInDir(filePath, fileName)
|
122
|
+
// .then(resolve) // 如果找到了目标文件,将结果resolve
|
123
|
+
// .catch(reject); // 如果在子目录中出错,将错误reject
|
124
|
+
// } else if (file.startsWith(fileName) && file.endsWith(expandedName)) {
|
125
|
+
// resolve(filePath); // 如果找到了目标文件,将结果resolve
|
126
|
+
// }
|
127
|
+
// });
|
128
|
+
// }
|
129
|
+
|
130
|
+
// // 如果遍历完了所有文件和子目录仍未找到目标文件,resolve一个null表示未找到
|
131
|
+
// resolve(null);
|
132
|
+
// });
|
133
|
+
// });
|
134
|
+
// }
|
135
|
+
|
136
|
+
/**
|
137
|
+
* 生成预览图 indexFilePath: output/0
|
138
|
+
* originFilePath E:\workspace\图片测试\photos\abc222.png
|
139
|
+
*/
|
140
|
+
const PriviewPhoto = (indexFilePath, originFilePath, fileName) => {
|
141
|
+
//存放预览图图的文件夹
|
142
|
+
const outputDir = path.join(indexFilePath, SCREENSHOT_DIR);
|
143
|
+
ensureDirSync(outputDir);
|
144
|
+
|
145
|
+
const outputFile = path.join(outputDir, fileName);
|
146
|
+
|
147
|
+
return new Promise((resolve, reject) => {
|
148
|
+
const watermarkScreenshotsComand = ffmpeg(originFilePath);
|
149
|
+
watermarkScreenshotsComand
|
150
|
+
.size("1280x?")
|
151
|
+
.output(outputFile)
|
152
|
+
.on("error", (err) => {
|
153
|
+
logger("截图预览图出错: " + err);
|
154
|
+
reject();
|
155
|
+
})
|
156
|
+
.on("end", () => {
|
157
|
+
logger("预览图完成: " + outputFile);
|
158
|
+
resolve();
|
159
|
+
})
|
160
|
+
.run();
|
161
|
+
});
|
162
|
+
};
|
163
|
+
|
164
|
+
/**
|
165
|
+
* 生成水印预览图
|
166
|
+
*/
|
167
|
+
const watermarkPriviewPhoto = (indexFilePath, originFilePath, fileName) => {
|
168
|
+
//存放水印截图的文件夹
|
169
|
+
const outputDir = path.join(indexFilePath, ZIP_SCREENSHOT_WM_DIR);
|
170
|
+
const inputDir = path.join(indexFilePath, SCREENSHOT_DIR, fileName);
|
171
|
+
ensureDirSync(outputDir);
|
172
|
+
|
173
|
+
const outputFile = path.join(outputDir, fileName);
|
174
|
+
|
175
|
+
return new Promise((resolve, reject) => {
|
176
|
+
const watermarkScreenshotsComand = ffmpeg(inputDir);
|
177
|
+
watermarkScreenshotsComand
|
178
|
+
.input(watermarkImage)
|
179
|
+
.complexFilter("overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2")
|
180
|
+
.output(outputFile)
|
181
|
+
.on("error", (err) => {
|
182
|
+
logger("截图添加水印出错: " + err);
|
183
|
+
reject();
|
184
|
+
})
|
185
|
+
.on("end", () => {
|
186
|
+
logger("截图水印添加完成: " + outputFile);
|
187
|
+
resolve();
|
188
|
+
})
|
189
|
+
.run();
|
190
|
+
});
|
191
|
+
};
|
192
|
+
|
193
|
+
/**
|
194
|
+
* 确保目录存在,如果不存在则创建它
|
195
|
+
*/
|
196
|
+
function ensureDirSync(dirpath) {
|
197
|
+
try {
|
198
|
+
if (!fs.existsSync(dirpath)) {
|
199
|
+
fs.mkdirSync(dirpath, { recursive: true });
|
200
|
+
logger(`目录创建成功:${dirpath}`);
|
201
|
+
}
|
202
|
+
} catch (err) {
|
203
|
+
logger(`创建目录时出错:${err}`);
|
204
|
+
throw err;
|
205
|
+
}
|
206
|
+
}
|
207
|
+
|
208
|
+
/**
|
209
|
+
* 打包物料
|
210
|
+
*/
|
211
|
+
const archiveZip = (fileName, inputPath, originFilePath) => {
|
212
|
+
const zipDir = path.join(inputPath, "zip");
|
213
|
+
const timestamp = new Date().getTime();
|
214
|
+
|
215
|
+
ensureDirSync(zipDir);
|
216
|
+
const zipStream = fs.createWriteStream(
|
217
|
+
path.join(zipDir, `package${timestamp}.zip`)
|
218
|
+
);
|
219
|
+
const archive = archiver("zip", {
|
220
|
+
zlib: { level: 9 },
|
221
|
+
});
|
222
|
+
|
223
|
+
return new Promise((resolve, reject) => {
|
224
|
+
zipStream.on("close", function () {
|
225
|
+
logger("压缩数据:" + archive.pointer() + " total bytes");
|
226
|
+
logger(
|
227
|
+
"完成归档archiver has been finalized and the output file descriptor has closed."
|
228
|
+
);
|
229
|
+
resolve();
|
230
|
+
});
|
231
|
+
|
232
|
+
archive.on("warning", function (err) {
|
233
|
+
if (err.code === "ENOENT") {
|
234
|
+
logger("压缩-warning:" + err);
|
235
|
+
} else {
|
236
|
+
throw err;
|
237
|
+
}
|
238
|
+
});
|
239
|
+
|
240
|
+
archive.on("error", function (err) {
|
241
|
+
logger("压缩失败!" + err);
|
242
|
+
reject();
|
243
|
+
});
|
244
|
+
|
245
|
+
archive.pipe(zipStream);
|
246
|
+
const directories = [ZIP_SCREENSHOT_WM_DIR, SCREENSHOT_DIR];
|
247
|
+
|
248
|
+
directories.forEach((dir) => {
|
249
|
+
const dirPath = path.join(inputPath, dir);
|
250
|
+
archive.directory(dirPath, dir);
|
251
|
+
});
|
252
|
+
|
253
|
+
archive.file(originFilePath, {
|
254
|
+
name: path.join(SOURCE_PHOTO_DIR, fileName),
|
255
|
+
});
|
256
|
+
// 完成归档
|
257
|
+
archive.finalize();
|
258
|
+
});
|
259
|
+
};
|
260
|
+
|
261
|
+
/**
|
262
|
+
* 获取 元数据
|
263
|
+
*/
|
264
|
+
const getMetadata = async (
|
265
|
+
fileName,
|
266
|
+
indexFilePath,
|
267
|
+
originFilePath,
|
268
|
+
{ rowFileName, title, keyword }
|
269
|
+
) => {
|
270
|
+
//源图片数据
|
271
|
+
const photoMetadataComand = ffmpeg(originFilePath);
|
272
|
+
//预览图数据
|
273
|
+
const photoInputPath = path.join(indexFilePath, SCREENSHOT_DIR, fileName);
|
274
|
+
const photoPreviewMetadataComand = ffmpeg(photoInputPath);
|
275
|
+
|
276
|
+
const metaDataParams = {
|
277
|
+
photo_id: rowFileName,
|
278
|
+
width: "",
|
279
|
+
height: "",
|
280
|
+
format: "",
|
281
|
+
size: "",
|
282
|
+
pr: 160,
|
283
|
+
dpi: 0,
|
284
|
+
is_government: 0,
|
285
|
+
common_width: "",
|
286
|
+
common_height: "",
|
287
|
+
dujia: 0,
|
288
|
+
xiaoxiang: 0,
|
289
|
+
title,
|
290
|
+
keyword,
|
291
|
+
en_keyword: "",
|
292
|
+
// preview_path: "",
|
293
|
+
// markImage_path: "",
|
294
|
+
// photo_path: "",
|
295
|
+
// common_image_path: "",
|
296
|
+
// en_keyword: "",
|
297
|
+
plate_id: 3,
|
298
|
+
transform_plate_id: 3,
|
299
|
+
tag_id: 47,
|
300
|
+
userid: 1003,
|
301
|
+
username: "美好景象",
|
302
|
+
demand_kind: 3,
|
303
|
+
source_from: 71,
|
304
|
+
file: "",
|
305
|
+
};
|
306
|
+
|
307
|
+
await new Promise((resolve, reject) => {
|
308
|
+
photoMetadataComand.ffprobe(function (err, metadata) {
|
309
|
+
// console.log("metadata");
|
310
|
+
// console.log(JSON.stringify(metadata));
|
311
|
+
if (metadata) {
|
312
|
+
const formatStream = metadata.format;
|
313
|
+
const photoStream = metadata.streams.find(
|
314
|
+
(s) => s.codec_type === "video"
|
315
|
+
);
|
316
|
+
|
317
|
+
metaDataParams.width = photoStream.width;
|
318
|
+
metaDataParams.height = photoStream.height;
|
319
|
+
// metaDataParams.format = formatStream.format_name;
|
320
|
+
metaDataParams.format = "jpg";
|
321
|
+
metaDataParams.size = formatStream.size;
|
322
|
+
|
323
|
+
resolve();
|
324
|
+
} else {
|
325
|
+
reject(err);
|
326
|
+
}
|
327
|
+
});
|
328
|
+
});
|
329
|
+
await new Promise((resolve, reject) => {
|
330
|
+
photoPreviewMetadataComand.ffprobe(function (err, metadata) {
|
331
|
+
if (metadata) {
|
332
|
+
const photoStream = metadata.streams.find(
|
333
|
+
(s) => s.codec_type === "video"
|
334
|
+
);
|
335
|
+
|
336
|
+
metaDataParams.common_width = photoStream.width;
|
337
|
+
metaDataParams.common_height = photoStream.height;
|
338
|
+
resolve();
|
339
|
+
} else {
|
340
|
+
reject(err);
|
341
|
+
}
|
342
|
+
});
|
343
|
+
});
|
344
|
+
|
345
|
+
return metaDataParams;
|
346
|
+
};
|
347
|
+
|
348
|
+
/**
|
349
|
+
* 接口
|
350
|
+
*/
|
351
|
+
const postData = (dataParams, indexFilePath) => {
|
352
|
+
const formData = new FormData();
|
353
|
+
|
354
|
+
const zipFiles = fs
|
355
|
+
.readdirSync(path.join(indexFilePath, ZIP_FILES_DIR))
|
356
|
+
.find((file) => file.endsWith(".zip"));
|
357
|
+
|
358
|
+
const packageZip = path.join(indexFilePath, ZIP_FILES_DIR, zipFiles);
|
359
|
+
|
360
|
+
formData.append("file", fs.createReadStream(packageZip));
|
361
|
+
for (const key in dataParams) {
|
362
|
+
if (Object.hasOwnProperty.call(dataParams, key)) {
|
363
|
+
const value = dataParams[key];
|
364
|
+
formData.append(key, value);
|
365
|
+
}
|
366
|
+
}
|
367
|
+
|
368
|
+
logger("等待接口返回结果……");
|
369
|
+
|
370
|
+
// return axios.post("http://192.168.102.61:9999/upload/photo", formData, {
|
371
|
+
return axios.post("http://127.0.0.1:9999/upload/photo", formData, {
|
372
|
+
headers: {
|
373
|
+
"Content-Type": "multipart/form-data",
|
374
|
+
},
|
375
|
+
timeout: 300000,
|
376
|
+
});
|
377
|
+
};
|
378
|
+
|
379
|
+
/**
|
380
|
+
* 任务
|
381
|
+
*/
|
382
|
+
const task = async (row, index) => {
|
383
|
+
logger(
|
384
|
+
"**************************" + row.fileName + "**************************"
|
385
|
+
);
|
386
|
+
// Excel的列名分别为: fileName title keyword
|
387
|
+
// 表格中文件名无后缀,遂手动添加写死为mp4
|
388
|
+
let fileName = row.fileName;
|
389
|
+
const rowFileName = row.fileName;
|
390
|
+
const title = row.title;
|
391
|
+
const keywordArr = row.keyword.split(",");
|
392
|
+
const filteredArray = keywordArr.filter((item) => item.trim() !== "");
|
393
|
+
const keyword = filteredArray.join(" ");
|
394
|
+
|
395
|
+
if (!fileName.includes(".")) {
|
396
|
+
fileName = row.fileName + expandedName;
|
397
|
+
}
|
398
|
+
|
399
|
+
const getPathStartTime = new Date();
|
400
|
+
// 源图片文件夹路径
|
401
|
+
const originFilePath = await findFileInDir(
|
402
|
+
path.join(workDir, ORIGIN_FILE_DIR),
|
403
|
+
fileName
|
404
|
+
);
|
405
|
+
const getPathEndTime = new Date();
|
406
|
+
const timeInSeconds = ((getPathEndTime - getPathStartTime) / 1000).toFixed(2);
|
407
|
+
|
408
|
+
logger(`第${index}条Path路径搜索时间:${timeInSeconds}秒`);
|
409
|
+
logger(`-------------------${new Date()}------------------`);
|
410
|
+
|
411
|
+
console.log("originFilePath:" + originFilePath);
|
412
|
+
console.log("fileName:" + fileName);
|
413
|
+
|
414
|
+
if (!originFilePath) {
|
415
|
+
logger(`图片文件 ${fileName} 不存在`);
|
416
|
+
return;
|
417
|
+
}
|
418
|
+
|
419
|
+
//index文件夹 output/0
|
420
|
+
const indexFilePath = path.join(workDir, "output", index + "");
|
421
|
+
|
422
|
+
try {
|
423
|
+
const workStartTime = new Date();
|
424
|
+
await fs_asnyc.access(originFilePath, fs_asnyc.constants.F_OK);
|
425
|
+
logFileSize(originFilePath);
|
426
|
+
await PriviewPhoto(indexFilePath, originFilePath, fileName);
|
427
|
+
await watermarkPriviewPhoto(indexFilePath, originFilePath, fileName);
|
428
|
+
await archiveZip(fileName, indexFilePath, originFilePath);
|
429
|
+
const dataParams = await getMetadata(
|
430
|
+
fileName,
|
431
|
+
indexFilePath,
|
432
|
+
originFilePath,
|
433
|
+
{
|
434
|
+
rowFileName,
|
435
|
+
title,
|
436
|
+
keyword,
|
437
|
+
}
|
438
|
+
);
|
439
|
+
const workEndTime = new Date();
|
440
|
+
const timeInSeconds = ((workEndTime - workStartTime) / 1000).toFixed(2);
|
441
|
+
|
442
|
+
logger(`第${index}条4090处理总时间:${timeInSeconds}秒`);
|
443
|
+
logger(`-------------------${new Date()}------------------`);
|
444
|
+
|
445
|
+
const postStartTime = new Date();
|
446
|
+
const resData = await postData(dataParams, indexFilePath);
|
447
|
+
const postEndTime = new Date();
|
448
|
+
const timeInSeconds1 = ((postEndTime - postStartTime) / 1000).toFixed(2);
|
449
|
+
|
450
|
+
logger(`第${index}条接口处理总时间:${timeInSeconds1}秒`);
|
451
|
+
logger(`-------------------${new Date()}------------------`);
|
452
|
+
|
453
|
+
if (resData.data.code === 200) {
|
454
|
+
logger("请求成功!");
|
455
|
+
logger(resData.data.code);
|
456
|
+
console.log(resData.data);
|
457
|
+
//删除文件夹
|
458
|
+
fs.rmdirSync(indexFilePath, { recursive: true });
|
459
|
+
} else {
|
460
|
+
throw new Error("请求失败!" + resData.data.msg);
|
461
|
+
}
|
462
|
+
|
463
|
+
logger(
|
464
|
+
`----------------------------------------第${index}条结束---------------------------------end`
|
465
|
+
);
|
466
|
+
} catch (error) {
|
467
|
+
// 可以约定code,来表示不同的错误信息
|
468
|
+
if (error.code === "ENOENT") {
|
469
|
+
logger(`图片文件 ${fileName} 不存在`);
|
470
|
+
} else {
|
471
|
+
logger("图片任务处理失败:" + error);
|
472
|
+
logger(error);
|
473
|
+
}
|
474
|
+
fs.rmdirSync(indexFilePath, { recursive: true });
|
475
|
+
disposeError(fileName);
|
476
|
+
}
|
477
|
+
};
|
478
|
+
|
479
|
+
/**
|
480
|
+
* 解析Excel数据
|
481
|
+
*/
|
482
|
+
const transitionExcelToJSON = () => {
|
483
|
+
//当前任务hash
|
484
|
+
const hashOrigin = generateUniqueHash();
|
485
|
+
const hash = hashOrigin.slice(0, 8);
|
486
|
+
logger("图片批量任务任务开始---" + hash);
|
487
|
+
logger("当前目录: " + workDir);
|
488
|
+
logger("工作目录: " + __dirname);
|
489
|
+
|
490
|
+
const jsonData = readExcel(excelDir);
|
491
|
+
|
492
|
+
const run = (index) => {
|
493
|
+
try {
|
494
|
+
logger(
|
495
|
+
`run-------------------------------------第${index}条开始------------------------------------`
|
496
|
+
);
|
497
|
+
logger(`-------------------${new Date()}------------------`);
|
498
|
+
const row = jsonData[index];
|
499
|
+
|
500
|
+
if (!row) {
|
501
|
+
return;
|
502
|
+
}
|
503
|
+
task(row, index)
|
504
|
+
.then(() => {
|
505
|
+
taskIndex++;
|
506
|
+
run(taskIndex);
|
507
|
+
})
|
508
|
+
.catch(() => {
|
509
|
+
taskIndex++;
|
510
|
+
run(taskIndex);
|
511
|
+
});
|
512
|
+
} catch (error) {
|
513
|
+
logger("捕获错误!" + error);
|
514
|
+
taskIndex++;
|
515
|
+
run(taskIndex);
|
516
|
+
}
|
517
|
+
};
|
518
|
+
|
519
|
+
for (let i = 0; i < queueCount; i++) {
|
520
|
+
run(i + taskIndex);
|
521
|
+
}
|
522
|
+
};
|
523
|
+
|
524
|
+
transitionExcelToJSON();
|