選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

471 行
16 KiB

1年前
1年前
1年前
1年前
  1. const http = require("http");
  2. const querystring = require("querystring");
  3. const url = require("url");
  4. const fs = require("fs");
  5. const path = require("path");
  6. const { app, dialog } = require("electron");
  7. const XLSX = require("xlsx");
  8. const formidable = require("formidable");
  9. const express = require("express");
  10. const multer = require("multer");
  11. const cors = require("cors");
  12. function travel(dir, callback) {
  13. fs.readdirSync(dir).forEach((file) => {
  14. const pathname = path.join(dir, file);
  15. if (fs.statSync(pathname).isDirectory()) {
  16. travel(pathname, callback);
  17. } else {
  18. callback(pathname);
  19. }
  20. });
  21. }
  22. function compare(p) {
  23. //这是比较函数
  24. return function (m, n) {
  25. let a = m[p];
  26. let b = n[p];
  27. return b - a; //降序
  28. };
  29. }
  30. function getDir() {
  31. if (__dirname.indexOf("app") >= 0 && __dirname.indexOf("sources") >= 0) {
  32. if (process.platform == "darwin") {
  33. return app.getPath("userData");
  34. } else {
  35. return path.join(__dirname, "../../..");
  36. }
  37. } else {
  38. return __dirname;
  39. }
  40. }
  41. function getEasySpiderLocation() {
  42. if (__dirname.indexOf("app") >= 0 && __dirname.indexOf("sources") >= 0) {
  43. if (process.platform == "darwin") {
  44. return path.join(__dirname, "../../../");
  45. } else {
  46. return path.join(__dirname, "../../../");
  47. }
  48. } else {
  49. return __dirname;
  50. }
  51. }
  52. if (!fs.existsSync(path.join(getDir(), "tasks"))) {
  53. fs.mkdirSync(path.join(getDir(), "tasks"));
  54. }
  55. if (!fs.existsSync(path.join(getDir(), "execution_instances"))) {
  56. fs.mkdirSync(path.join(getDir(), "execution_instances"));
  57. }
  58. if (!fs.existsSync(path.join(getDir(), "config.json"))) {
  59. // Generate config.json
  60. fs.writeFileSync(
  61. path.join(getDir(), "config.json"),
  62. JSON.stringify({
  63. webserver_address: "http://localhost",
  64. webserver_port: 8074,
  65. user_data_folder: "./user_data",
  66. debug: false,
  67. copyright: 0,
  68. sys_arch: require("os").arch(),
  69. mysql_config_path: "./mysql_config.json",
  70. absolute_user_data_folder:
  71. "D:\\Document\\Projects\\EasySpider\\ElectronJS\\user_data",
  72. })
  73. );
  74. }
  75. exports.getDir = getDir;
  76. exports.getEasySpiderLocation = getEasySpiderLocation;
  77. FileMimes = JSON.parse(
  78. fs.readFileSync(path.join(__dirname, "mime.json")).toString()
  79. );
  80. const fileServer = express();
  81. const upload = multer({ dest: path.join(getDir(), "Data/") });
  82. fileServer.use(cors());
  83. fileServer.post("/excelUpload", upload.single("file"), (req, res) => {
  84. let workbook = XLSX.readFile(req.file.path);
  85. let sheet_name_list = workbook.SheetNames;
  86. let data = XLSX.utils.sheet_to_json(workbook.Sheets[sheet_name_list[0]]);
  87. let result = data.reduce((acc, obj) => {
  88. Object.keys(obj).forEach((key) => {
  89. if (!acc[key]) {
  90. acc[key] = [];
  91. }
  92. acc[key].push(obj[key]);
  93. });
  94. return acc;
  95. }, {});
  96. // console.log(data);
  97. // delete file after reading
  98. fs.unlink(req.file.path, (err) => {
  99. if (err) {
  100. console.error(err);
  101. return;
  102. }
  103. // file removed
  104. });
  105. res.send(JSON.stringify(result));
  106. });
  107. fileServer.listen(8075, () => {
  108. console.log("Server listening on http://localhost:8075");
  109. });
  110. exports.start = function (port = 8074) {
  111. http
  112. .createServer(function (req, res) {
  113. let body = "";
  114. res.setHeader("Access-Control-Allow-Origin", "*"); // 设置可访问的源
  115. // 解析参数
  116. const pathName = url.parse(req.url).pathname;
  117. if (pathName == "/excelUpload" && req.method.toLowerCase() === "post") {
  118. // // parse a file upload
  119. // let form = new formidable.IncomingForm();
  120. // // Set the max file size
  121. // form.maxFileSize = 200 * 1024 * 1024; // 200MB
  122. // form.parse(req, function (err, fields, files) {
  123. // console.log("excelUpload")
  124. // console.log(err, fields, files);
  125. // let oldpath = files.file.path;
  126. // let workbook = XLSX.readFile(oldpath);
  127. // let sheet_name_list = workbook.SheetNames;
  128. // let data = XLSX.utils.sheet_to_json(workbook.Sheets[sheet_name_list[0]]);
  129. // console.log(data);
  130. // res.end('File uploaded and read successfully.');
  131. // });
  132. } else if (pathName.indexOf(".") < 0) {
  133. //如果没有后缀名, 则为后台请求
  134. res.writeHead(200, { "Content-Type": "application/json" });
  135. }
  136. // else if(pathName.indexOf("index.html") >= 0) {
  137. // fs.readFile(path.join(__dirname,"src", pathName), async (err, data) => {
  138. // if (err) {
  139. // res.writeHead(404, { 'Content-Type': 'text/html;charset="utf-8"' })
  140. // res.end(err.message)
  141. // return;
  142. // }
  143. // if (!err) {
  144. // // 3. 针对不同的文件返回不同的内容头
  145. // let extname = path.extname(pathName);
  146. // let mime = FileMimes[extname]
  147. // res.writeHead(200, { 'Content-Type': mime + ';charset="utf-8"' })
  148. // res.end(data);
  149. // return;
  150. // }
  151. // })
  152. // }
  153. else {
  154. //如果有后缀名, 则为前端请求
  155. // console.log(path.join(__dirname,"src/taskGrid", pathName));
  156. fs.readFile(
  157. path.join(__dirname, "src", pathName),
  158. async (err, data) => {
  159. if (err) {
  160. res.writeHead(404, {
  161. "Content-Type": 'text/html;charset="utf-8"',
  162. });
  163. res.end(err.message);
  164. return;
  165. }
  166. if (!err) {
  167. // 3. 针对不同的文件返回不同的内容头
  168. let extname = path.extname(pathName);
  169. let mime = FileMimes[extname];
  170. res.writeHead(200, { "Content-Type": mime + ';charset="utf-8"' });
  171. res.end(data);
  172. return;
  173. }
  174. }
  175. );
  176. }
  177. req.on("data", function (chunk) {
  178. body += chunk;
  179. });
  180. req.on("end", function () {
  181. // 设置响应头部信息及编码
  182. if (pathName == "/queryTasks") {
  183. //查询所有服务信息,只包括id和服务名称
  184. output = [];
  185. travel(path.join(getDir(), "tasks"), function (pathname) {
  186. const data = fs.readFileSync(pathname, "utf8");
  187. let stat = fs.statSync(pathname, "utf8");
  188. // parse JSON string to JSON object
  189. // console.log("\n\n\n\n\n", pathname, '\n\n\n\n\n\n');
  190. if (pathname.indexOf(".json") >= 0) {
  191. const task = JSON.parse(data);
  192. let item = {
  193. id: task.id,
  194. name: task.name,
  195. url: task.url,
  196. mtime: stat.mtime,
  197. links: task.links,
  198. desc: task.desc,
  199. };
  200. if (item.id != -2) {
  201. output.push(item);
  202. }
  203. }
  204. });
  205. output.sort(compare("mtime"));
  206. res.write(JSON.stringify(output));
  207. res.end();
  208. } else if (pathName == "/queryOSVersion") {
  209. res.write(
  210. JSON.stringify({ version: process.platform, bit: process.arch })
  211. );
  212. res.end();
  213. } else if (pathName == "/queryExecutionInstances") {
  214. //查询所有服务信息,只包括id和服务名称
  215. output = [];
  216. travel(
  217. path.join(getDir(), "execution_instances"),
  218. function (pathname) {
  219. const data = fs.readFileSync(pathname, "utf8");
  220. // parse JSON string to JSON object
  221. const task = JSON.parse(data);
  222. let item = {
  223. id: task.id,
  224. name: task.name,
  225. url: task.url,
  226. };
  227. if (item.id != -2) {
  228. output.push(item);
  229. }
  230. }
  231. );
  232. res.write(JSON.stringify(output));
  233. res.end();
  234. } else if (pathName == "/queryTask") {
  235. let params = url.parse(req.url, true).query;
  236. try {
  237. let tid = parseInt(params.id);
  238. const data = fs.readFileSync(
  239. path.join(getDir(), `tasks/${tid}.json`),
  240. "utf8"
  241. );
  242. // parse JSON string to JSON object
  243. res.write(data);
  244. res.end();
  245. } catch (error) {
  246. res.write(
  247. JSON.stringify({
  248. error: "Cannot find task based on specified task ID.",
  249. })
  250. );
  251. res.end();
  252. }
  253. } else if (pathName == "/queryExecutionInstance") {
  254. let params = url.parse(req.url, true).query;
  255. try {
  256. let tid = parseInt(params.id);
  257. const data = fs.readFileSync(
  258. path.join(getDir(), `execution_instances/${tid}.json`),
  259. "utf8"
  260. );
  261. // parse JSON string to JSON object
  262. res.write(data);
  263. res.end();
  264. } catch (error) {
  265. res.write(
  266. JSON.stringify({
  267. error:
  268. "Cannot find execution instance based on specified execution ID.",
  269. })
  270. );
  271. res.end();
  272. }
  273. } else if (pathName == "/") {
  274. res.write("Hello World!", "utf8");
  275. res.end();
  276. } else if (pathName == "/deleteTask") {
  277. let params = url.parse(req.url, true).query;
  278. try {
  279. let tid = parseInt(params.id);
  280. let data = fs.readFileSync(
  281. path.join(getDir(), `tasks/${tid}.json`),
  282. "utf8"
  283. );
  284. data = JSON.parse(data);
  285. data.id = -2;
  286. data = JSON.stringify(data);
  287. // write JSON string to a file
  288. fs.writeFile(
  289. path.join(getDir(), `tasks/${tid}.json`),
  290. data,
  291. (err) => {
  292. if (err) {
  293. throw err;
  294. }
  295. }
  296. );
  297. res.write(
  298. JSON.stringify({ success: "Task has been deleted successfully." })
  299. );
  300. res.end();
  301. } catch (error) {
  302. res.write(
  303. JSON.stringify({
  304. error: "Cannot find task based on specified task ID.",
  305. })
  306. );
  307. res.end();
  308. }
  309. } else if (pathName == "/manageTask") {
  310. body = querystring.parse(body);
  311. data = JSON.parse(body.params);
  312. let id = data["id"];
  313. if (data["id"] == -1) {
  314. file_names = [];
  315. fs.readdirSync(path.join(getDir(), "tasks")).forEach((file) => {
  316. try {
  317. if (file.split(".")[1] == "json") {
  318. file_names.push(parseInt(file.split(".")[0]));
  319. }
  320. } catch (error) {}
  321. });
  322. if (file_names.length == 0) {
  323. id = 0;
  324. } else {
  325. id = Math.max(...file_names) + 1;
  326. }
  327. data["id"] = id;
  328. // write JSON string to a fil
  329. }
  330. if (data["outputFormat"] == "mysql") {
  331. let mysql_config_path = path.join(getDir(), "mysql_config.json");
  332. // 检测文件是否存在
  333. fs.access(mysql_config_path, fs.F_OK, (err) => {
  334. if (err) {
  335. console.log("File does not exist. Creating...");
  336. // 文件不存在,创建文件
  337. const config = {
  338. host: "localhost",
  339. port: 3306,
  340. username: "your_username",
  341. password: "your_password",
  342. database: "your_database",
  343. };
  344. fs.writeFile(
  345. mysql_config_path,
  346. JSON.stringify(config, null, 4),
  347. (err) => {
  348. if (err) throw err;
  349. console.log("File is created successfully.");
  350. }
  351. );
  352. } else {
  353. console.log("File exists.");
  354. }
  355. });
  356. }
  357. data = JSON.stringify(data);
  358. // write JSON string to a file
  359. fs.writeFile(
  360. path.join(getDir(), `tasks/${id}.json`),
  361. data,
  362. (err) => {}
  363. );
  364. res.write(id.toString(), "utf8");
  365. res.end();
  366. } else if (pathName == "/invokeTask") {
  367. body = querystring.parse(body);
  368. let data = JSON.parse(body.params);
  369. let id = body.id;
  370. let task = fs.readFileSync(
  371. path.join(getDir(), `tasks/${id}.json`),
  372. "utf8"
  373. );
  374. task = JSON.parse(task);
  375. try {
  376. task["links"] = data["urlList_0"];
  377. if (task["links"] == undefined) {
  378. task["links"] = "about:blank";
  379. }
  380. } catch (error) {
  381. task["links"] = "about:blank";
  382. }
  383. for (const [key, value] of Object.entries(data)) {
  384. for (let i = 0; i < task["inputParameters"].length; i++) {
  385. if (key === task["inputParameters"][i]["name"]) {
  386. // 能调用
  387. const nodeId = parseInt(task["inputParameters"][i]["nodeId"]);
  388. const node = task["graph"][nodeId];
  389. if (node["option"] === 1) {
  390. node["parameters"]["links"] = value;
  391. } else if (node["option"] === 4) {
  392. node["parameters"]["value"] = value;
  393. } else if (
  394. node["option"] === 8 &&
  395. node["parameters"]["loopType"] === 0
  396. ) {
  397. node["parameters"]["exitCount"] = parseInt(value);
  398. } else if (node["option"] === 8) {
  399. node["parameters"]["textList"] = value;
  400. }
  401. break;
  402. }
  403. }
  404. }
  405. let file_names = [];
  406. fs.readdirSync(path.join(getDir(), "execution_instances")).forEach(
  407. (file) => {
  408. try {
  409. if (file.split(".")[1] == "json") {
  410. file_names.push(parseInt(file.split(".")[0]));
  411. }
  412. console.log(file);
  413. } catch (error) {}
  414. }
  415. );
  416. let eid = 0;
  417. if (file_names.length != 0) {
  418. eid = Math.max(...file_names) + 1;
  419. }
  420. if (body["EID"] != "" && body["EID"] != undefined) {
  421. //覆盖原有的执行实例
  422. eid = parseInt(body["EID"]);
  423. }
  424. task["id"] = eid;
  425. task = JSON.stringify(task);
  426. fs.writeFile(
  427. path.join(getDir(), `execution_instances/${eid}.json`),
  428. task,
  429. (err) => {}
  430. );
  431. res.write(eid.toString(), "utf8");
  432. res.end();
  433. } else if (pathName == "/getConfig") {
  434. let config_file = fs.readFileSync(
  435. path.join(getDir(), `config.json`),
  436. "utf8"
  437. );
  438. config_file = JSON.parse(config_file);
  439. res.write(JSON.stringify(config_file));
  440. res.end();
  441. } else if (pathName == "/setUserDataFolder") {
  442. let config = fs.readFileSync(
  443. path.join(getDir(), `config.json`),
  444. "utf8"
  445. );
  446. config = JSON.parse(config);
  447. body = querystring.parse(body);
  448. config["user_data_folder"] = body["user_data_folder"];
  449. config = JSON.stringify(config);
  450. fs.writeFile(path.join(getDir(), `config.json`), config, (err) => {});
  451. res.write(
  452. JSON.stringify({
  453. success: "User data folder has been set successfully.",
  454. })
  455. );
  456. res.end();
  457. }
  458. });
  459. })
  460. .listen(port);
  461. console.log("Server has started.");
  462. };