HttpHandlers.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. using DaJiaoYan.Models;
  2. using DaJiaoYan.Utils;
  3. using DaJiaoYan.Variables;
  4. using OpenCvSharp;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.IO;
  8. using System.Linq;
  9. using System.Net;
  10. using System.Threading.Tasks;
  11. namespace DaJiaoYan.Services
  12. {
  13. struct ScanResult
  14. {
  15. public string Filename;
  16. public int Index;
  17. }
  18. internal class PingHandler : HttpHandler
  19. {
  20. private ResponseData pongResponse = new ResponseData { Code = 200, Data = "pong" };
  21. public PingHandler(AsyncHttpServer httpServer) : base(httpServer)
  22. {
  23. }
  24. public override void Get(HttpListenerRequest request, HttpListenerResponse response)
  25. {
  26. Json(ref response, ref pongResponse);
  27. }
  28. }
  29. internal class ScannerHandler : HttpHandler
  30. {
  31. public ScannerHandler(AsyncHttpServer httpServer) : base(httpServer)
  32. {
  33. }
  34. public override void Get(HttpListenerRequest request, HttpListenerResponse response)
  35. {
  36. ResponseData result = new ResponseData { Code = 200, Data = Variables.Vars.Scanners };
  37. Json(ref response, ref result);
  38. }
  39. }
  40. public class ScanHandler : HttpHandler
  41. {
  42. public ScanHandler(AsyncHttpServer httpServer) : base(httpServer)
  43. {
  44. }
  45. public override async void Post(HttpListenerRequest request, HttpListenerResponse response)
  46. {
  47. ResponseData result = new ResponseData { Code = 200 };
  48. var form = this.HttpServer.ParseForm(ref request);
  49. form.TryGetValue("scanner", out string scanner);
  50. var files = new List<string>();
  51. var finished = false;
  52. result.Data = files;
  53. if (string.IsNullOrEmpty(scanner))
  54. {
  55. result.Code = 400;
  56. result.Errors = "请选择扫描仪";
  57. finished = true;
  58. }
  59. else if (!Vars.Scanners.Contains(scanner))
  60. {
  61. result.Code = 400;
  62. result.Errors = "请选择正确的扫描仪";
  63. finished = true;
  64. }
  65. else if (Scan.State == Scan.ScannerState.Running)
  66. {
  67. result.Code = 400;
  68. result.Errors = "正在扫描中";
  69. finished = true;
  70. }
  71. else
  72. {
  73. ScanTask scanTask = new ScanTask
  74. {
  75. Scanner = scanner,
  76. ImageDpi = 200,
  77. ImageSuffix = "png",
  78. Colorful = true,
  79. Path = Const.TMP_PATH,
  80. CapXferCount = 2,
  81. OnScanBegin = (bool begin, string err) =>
  82. {
  83. if (!begin)
  84. {
  85. result.Code = 400;
  86. result.Errors = err;
  87. finished = true;
  88. }
  89. },
  90. OnDeleScanFileCompleted = (string f, int index) =>
  91. {
  92. try
  93. {
  94. Mat img = Cv2.ImRead(f);
  95. if (img != null && img.Channels() > 1)
  96. {
  97. ImageUtils.Red2OtherColor(ref img, Scalar.Black);
  98. Mat dstImg = new Mat(img.Size(), MatType.CV_8UC1);
  99. Cv2.CvtColor(img, dstImg, ColorConversionCodes.BGR2GRAY);
  100. Cv2.ImWrite(f, dstImg);
  101. dstImg.Dispose();
  102. }
  103. files.Add(ImageUtils.ToBase64(f));
  104. img?.Dispose();
  105. }
  106. catch
  107. {
  108. }
  109. },
  110. OnScanTaskCompleted = () =>
  111. {
  112. result.Code = 200;
  113. finished = true;
  114. },
  115. OnScannerError = () =>
  116. {
  117. result.Code = 200;
  118. result.Errors = "扫描出错!";
  119. finished = true;
  120. }
  121. };
  122. Scan.Start(scanTask);
  123. while (!finished || files.Count < 2)
  124. {
  125. await Task.Delay(100);
  126. }
  127. }
  128. Json(ref response, ref result);
  129. }
  130. }
  131. public class UploadHandler : HttpHandler
  132. {
  133. public UploadHandler(AsyncHttpServer httpServer) : base(httpServer)
  134. {
  135. }
  136. /// <summary>
  137. /// 扫描图片上传接口
  138. /// </summary>
  139. /// <param name="request"></param>
  140. /// <param name="response"></param>
  141. public override async void Post(HttpListenerRequest request, HttpListenerResponse response)
  142. {
  143. ResponseData result = new ResponseData { Code = 200 };
  144. int ocrVer = 0;
  145. var form = this.HttpServer.ParseForm(ref request);
  146. form.TryGetValue("token", out string token);
  147. form.TryGetValue("type", out string type);
  148. form.TryGetValue("school_id", out string school_id);
  149. form.TryGetValue("campus_id", out string campus_id);
  150. form.TryGetValue("class_id", out string class_id);
  151. form.TryGetValue("test_id", out string test_id);
  152. form.TryGetValue("subject_id", out string subject_id);
  153. form.TryGetValue("is_school_no", out string is_school_no);
  154. form.TryGetValue("sign_weight", out string sign_weight);
  155. form.TryGetValue("marking_type", out string marking_type);
  156. form.TryGetValue("scanner", out string scanner);
  157. form.TryGetValue("directory", out string directory);
  158. form.TryGetValue("ver", out string ver);
  159. if (!string.IsNullOrEmpty(ver))
  160. {
  161. int.TryParse(ver, out ocrVer);
  162. }
  163. UploadHandlerPostParam param = new UploadHandlerPostParam(
  164. token, type, school_id, campus_id, class_id, test_id, subject_id, is_school_no, sign_weight, scanner, directory, marking_type,
  165. ocrVer
  166. );
  167. if (param.GetErrorType != UploadHandlerPostParam.ErrorType.None)
  168. {
  169. result.Code = 400;
  170. result.Errors = param.ErrorMessage;
  171. }
  172. else
  173. {
  174. if (param.Type == UploadHandlerPostParam.UploadType.Scan)
  175. {
  176. if (Scan.State == Scan.ScannerState.Running)
  177. {
  178. result.Code = 400;
  179. result.Errors = "正在扫描中,请稍候";
  180. }
  181. if (string.IsNullOrEmpty(scanner))
  182. {
  183. result.Code = 400;
  184. result.Errors = "请选择扫描仪";
  185. param.ScanFinish = true;
  186. }
  187. else if (!Vars.Scanners.Contains(scanner))
  188. {
  189. result.Code = 400;
  190. result.Errors = "请选择正确的扫描仪";
  191. param.ScanFinish = true;
  192. }
  193. else
  194. {
  195. AliyunOssClient ossClient = new AliyunOssClient(param.Token);
  196. if (!ossClient.AccessAvailable)
  197. {
  198. result.Code = 400;
  199. result.Errors = "没有上传权限,请检查";
  200. }
  201. else
  202. {
  203. string batchId = Functions.GenUUID();
  204. string uploadTaskInfoId = batchId;
  205. result.Data = batchId;
  206. UploadTask.deleNewUploadTask(uploadTaskInfoId);
  207. string path = Path.Combine(Const.TMP_PATH, campus_id.ToString(), test_id.ToString(), batchId);
  208. FileExts.CheckDirectory(path, true);
  209. param.Directory = path;
  210. object _locker = new object();
  211. ScanResultPost scanResult = new ScanResultPost(param);
  212. //List<string> files = new List<string>();
  213. List<ScanResult> scanFiles = new List<ScanResult>();
  214. int n = 0, finished = 0;
  215. const int BATCH_SIZE = 2; //扫描1张就上传
  216. bool uploadImage(string ossFn, string fn)
  217. {
  218. bool res = false;
  219. if (scanResult.MarkingType == UploadHandlerPostParam.MarkType.OnlineMarking)
  220. {
  221. try
  222. {
  223. Mat img = Cv2.ImRead(fn);
  224. if (img != null && img.Channels() > 1)
  225. {
  226. Mat dstImg = new Mat(img.Size(), MatType.CV_8UC1);
  227. Cv2.CvtColor(img, dstImg, ColorConversionCodes.BGR2GRAY);
  228. Cv2.ImWrite(fn, dstImg);
  229. img.Dispose();
  230. dstImg.Dispose();
  231. }
  232. img?.Dispose();
  233. }
  234. catch
  235. {
  236. }
  237. }
  238. res = ossClient.SimpleUpload(ossFn, fn);
  239. UploadTask.deleIncreaseUploadTask(uploadTaskInfoId);
  240. return res;
  241. }
  242. async void uploadedFilenames()
  243. {
  244. //Console.WriteLine($"n={n}, total={scanResult.Total}, finish={scanResult.Finish}");
  245. if (n >= BATCH_SIZE || scanResult.Finish)
  246. {
  247. List<Task> tasks = new List<Task>();
  248. ScanResultPost sr = new ScanResultPost(param);
  249. lock (_locker)
  250. {
  251. sr.Finish = scanResult.Finish;
  252. sr.Total = scanResult.Total;
  253. sr.BatchId = scanResult.BatchId;
  254. }
  255. for (int i = sr.Total - n; i < sr.Total; i++)
  256. {
  257. int idx = i;
  258. ScanResultPost.ImageInfo info = new ScanResultPost.ImageInfo()
  259. {
  260. Image = scanFiles[idx].Filename,
  261. HasError = 1,
  262. Index = scanFiles[idx].Index
  263. };
  264. sr.Images.Add(info);
  265. tasks.Add(Task.Run(() =>
  266. {
  267. if (uploadImage(scanFiles[idx].Filename, Path.Combine(path, Path.GetFileName(scanFiles[idx].Filename))))
  268. {
  269. info.HasError = 0;
  270. }
  271. }));
  272. }
  273. n = 0;
  274. await Task.Factory.StartNew(async () =>
  275. {
  276. await Task.WhenAll(tasks.ToArray());
  277. // 上传图片地址
  278. await Api.PostExaminationScanResult(sr, param.Token);
  279. Vars.UploadedCounterIncrease(tasks.Count);
  280. lock (_locker)
  281. {
  282. finished += BATCH_SIZE;
  283. }
  284. //UploadTask.deleIncreaseUploadTask(uploadTaskInfoId, BATCH_SIZE);
  285. });
  286. }
  287. }
  288. ScanTask scanTask = new ScanTask
  289. {
  290. Scanner = scanner,
  291. ImageDpi = 200,
  292. ImageSuffix = "jpg",
  293. Colorful = param.MarkingType == UploadHandlerPostParam.MarkType.LocalMarking,
  294. Path = path,
  295. CapXferCount = -1,
  296. OnScanBegin = (bool begin, string err) =>
  297. {
  298. if (!begin)
  299. {
  300. result.Code = 400;
  301. result.Errors = err;
  302. scanResult.Finish = true;
  303. }
  304. },
  305. OnDeleScanFileCompleted = (string f, int index) =>
  306. {
  307. try
  308. {
  309. Task.Factory.StartNew(() =>
  310. {
  311. string originFilename = Functions.GenUploadOriginImageName(param.TestId, param.CampusId, f, scanResult.BatchId);
  312. lock (_locker)
  313. {
  314. //files.Add(originFilename);
  315. scanFiles.Add(new ScanResult { Filename = originFilename, Index = index });
  316. n++;
  317. scanResult.Total++;
  318. }
  319. UploadTask.deleIncreaseScanTask(uploadTaskInfoId, 1);
  320. uploadedFilenames();
  321. });
  322. }
  323. catch
  324. {
  325. }
  326. },
  327. OnScanTaskCompleted = async () =>
  328. {
  329. result.Code = 200;
  330. if (scanFiles.Count > 0)
  331. {
  332. while (finished < scanResult.Total)
  333. {
  334. await Task.Delay(1000);
  335. }
  336. }
  337. scanResult.Finish = true;
  338. UploadTask.deleFinishScanTask(uploadTaskInfoId);
  339. },
  340. OnScannerError = () =>
  341. {
  342. result.Code = 200;
  343. result.Errors = "扫描出错!";
  344. scanResult.Finish = true;
  345. }
  346. };
  347. await Task.Factory.StartNew(async () =>
  348. {
  349. Scan.Start(scanTask);
  350. Vars.SetTaskStatus(batchId, false);
  351. while (!scanResult.Finish)
  352. {
  353. await Task.Delay(100);
  354. }
  355. uploadedFilenames();
  356. Vars.SetTaskStatus(batchId, true);
  357. UploadTask.deleFinishUploadTask(uploadTaskInfoId);
  358. });
  359. }
  360. }
  361. }
  362. else
  363. {
  364. var divideConfig = await Api.GetDividePartitionConfig(param.TestId, param.Token);
  365. int answerSheetsLength = 2;
  366. if (divideConfig != null)
  367. {
  368. answerSheetsLength = divideConfig.AnswerSheets.Length;
  369. }
  370. // 上传文件夹
  371. List<string> files = FileExts.GetImageFiles(param.Directory);
  372. if (divideConfig != null && files.Count > 0 && answerSheetsLength > 0 && files.Count % answerSheetsLength != 0)
  373. {
  374. result.Code = 400;
  375. result.Errors = "本地答卷数量与模板数量不一致,请核查";
  376. }
  377. else if (files.Count > 0)
  378. {
  379. AliyunOssClient ossClient = new AliyunOssClient(param.Token);
  380. if (!ossClient.AccessAvailable)
  381. {
  382. result.Code = 400;
  383. result.Errors = "没有上传权限,请检查";
  384. }
  385. else
  386. {
  387. const int BATCH_SIZE = 4; //作为一个批次上传的图片数量
  388. string uploadTaskInfoId = Functions.GenUUID();
  389. UploadTask.deleNewUploadTask(uploadTaskInfoId);
  390. UploadTask.deleIncreaseScanTask(uploadTaskInfoId, files.Count);
  391. UploadTask.deleFinishScanTask(uploadTaskInfoId);
  392. result.Data = uploadTaskInfoId;
  393. int n = 0, idx = 0;
  394. ScanResultPost scanResult = new ScanResultPost(param)
  395. {
  396. Total = files.Count
  397. };
  398. bool uploadImage(string ossFn, string fn)
  399. {
  400. bool res = false;
  401. MemoryStream ms = new MemoryStream();
  402. string suffix = Path.GetExtension(fn).ToLower();
  403. ImageEncodingParam imageEncodingParam = Vars.IMAGE_SAVE_PNG_PARAM;
  404. Mat img;
  405. if (suffix.Equals(".jpeg", StringComparison.OrdinalIgnoreCase) || suffix.Equals(".jpg", StringComparison.OrdinalIgnoreCase))
  406. {
  407. imageEncodingParam = Vars.IMAGE_SAVE_JPEG_PARAM;
  408. }
  409. if (scanResult.MarkingType == UploadHandlerPostParam.MarkType.OnlineMarking)
  410. {
  411. img = ImageUtils.Read(fn, ImreadModes.Grayscale);
  412. }
  413. else
  414. {
  415. img = ImageUtils.Read(fn);
  416. }
  417. if (img != null)
  418. {
  419. ms = img.ToMemoryStream(suffix, imageEncodingParam);
  420. res = ossClient.SimpleUpload(ossFn, ms);
  421. img?.Dispose();
  422. ms?.Dispose();
  423. }
  424. return res;
  425. }
  426. async Task uploadedFilenames()
  427. {
  428. //Console.WriteLine($"n={n}, total={scanResult.Total}, finish={scanResult.Finish}");
  429. List<Task> tasks = new List<Task>();
  430. if (n >= BATCH_SIZE || scanResult.Finish)
  431. {
  432. scanResult.Images.Clear();
  433. for (int i = 0; idx < scanResult.Total && i < n; i++)
  434. {
  435. int _k = idx;
  436. string originImageFilename = Functions.GenUploadOriginImageName(scanResult.TestId, scanResult.CampusId, files[_k], scanResult.BatchId);
  437. ScanResultPost.ImageInfo info = new ScanResultPost.ImageInfo() { Image = originImageFilename, HasError = 1 };
  438. scanResult.Images.Add(info);
  439. tasks.Add(Task.Run(() =>
  440. {
  441. if (uploadImage(originImageFilename, files[_k]))
  442. {
  443. Console.WriteLine($"{originImageFilename} uploaded.");
  444. info.HasError = 0;
  445. info.Index = _k + 1;
  446. UploadTask.deleIncreaseUploadTask(uploadTaskInfoId);
  447. }
  448. }));
  449. idx++;
  450. }
  451. n = 0;
  452. }
  453. Task.WaitAll(tasks.ToArray());
  454. // 上传图片地址
  455. await Api.PostExaminationScanResult(scanResult, param.Token);
  456. Vars.UploadedCounterIncrease(tasks.Count);
  457. }
  458. _ = Task.Factory.StartNew(async () =>
  459. {
  460. string batchId = scanResult.BatchId;
  461. Vars.SetTaskStatus(batchId, false);
  462. for (int i = 0; i < files.Count; i += BATCH_SIZE)
  463. {
  464. n = BATCH_SIZE;
  465. await uploadedFilenames();
  466. await Task.Delay(100);
  467. }
  468. scanResult.Finish = true;
  469. n = BATCH_SIZE;
  470. await uploadedFilenames();
  471. Vars.SetTaskStatus(batchId, true);
  472. UploadTask.deleFinishUploadTask(uploadTaskInfoId);
  473. });
  474. }
  475. }
  476. else
  477. {
  478. result.Code = 400;
  479. result.Errors = "没有可上传的图片";
  480. }
  481. }
  482. }
  483. Json(ref response, ref result);
  484. }
  485. public override void Get(HttpListenerRequest request, HttpListenerResponse response)
  486. {
  487. ResponseData result = new ResponseData { Code = 200 };
  488. string id = request.QueryString.Get("id");
  489. result.Data = UploadTask.deleGetUploadTask(id);
  490. Json(ref response, ref result);
  491. }
  492. }
  493. }