FileExporterManager.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. using Avalonia.Controls;
  2. using fis.Helpers;
  3. using fis.Log;
  4. using fis.Managers.Interfaces;
  5. using fis.Utilities;
  6. using fis.Utilities.Entities;
  7. using Newtonsoft.Json;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.IO;
  11. using System.IO.Compression;
  12. using System.Linq;
  13. using System.Threading;
  14. using System.Threading.Tasks;
  15. using fis.Utilities.FFMPEG;
  16. using FFMpegWrapper;
  17. namespace fis.Managers
  18. {
  19. public enum ExportStatus {
  20. Downloading,
  21. Packaging,
  22. Finished
  23. }
  24. internal class FileExporterManager : IFileExporterManager
  25. {
  26. private int _fileCount = 0;
  27. private string _destnationName;
  28. private string _downloadFolder;
  29. private CancellationTokenSource _cancelTokenSource;
  30. private CancellationToken _cancelToken;
  31. private int _fileFinishCount = 0;
  32. private ExportStatus _exportStatus;
  33. public bool IsCancelled => _cancelToken.IsCancellationRequested;
  34. public ExportStatus ExportStatus
  35. {
  36. get { return _exportStatus; }
  37. set {
  38. _exportStatus = value;
  39. var progress = Math.Round((double)_fileFinishCount / (double)_fileCount, 2);
  40. if (_exportStatus == ExportStatus.Packaging)
  41. {
  42. NotifyTheProgress(progress, _exportStatus);
  43. DoPackaging();
  44. return;
  45. }
  46. if (_exportStatus == ExportStatus.Finished)
  47. {
  48. progress = 1;
  49. }
  50. NotifyTheProgress(progress, _exportStatus);
  51. }
  52. }
  53. private void NotifyTheProgress(double progress, ExportStatus exportStatus)
  54. {
  55. var callString = PlatFormHelper.GetMethodStr(BrowserManager.NotificationName, TargetMethodName.UpdateExportProgess, new List<string>() {
  56. progress.ToString(),
  57. ((int)exportStatus).ToString()
  58. });
  59. BrowserManager.MainBrowser.ExecuteJavaScript(callString, null, 0);
  60. }
  61. private void DoPackaging()
  62. {
  63. FFmpegService.ForceCloseFFmpegIfStillAlive();
  64. ZipFile.CreateFromDirectory(_downloadFolder, _destnationName);
  65. ExportStatus = ExportStatus.Finished;
  66. DeleteTheTemps(_downloadFolder);
  67. }
  68. public void Dispose()
  69. {
  70. throw new NotImplementedException();
  71. }
  72. public bool AbortExportOperation()
  73. {
  74. _cancelTokenSource?.Cancel();
  75. _fileFinishCount = 0;
  76. ExportStatus = ExportStatus.Downloading;
  77. Task.Run(() =>
  78. {
  79. Thread.Sleep(500);
  80. DeleteTheTemps(_downloadFolder);
  81. }
  82. );
  83. return true;
  84. }
  85. public bool ExportPatientZipFile(string data, string fileName)
  86. {
  87. var dataObj = JsonConvert.DeserializeObject<ExportRemedicalZipFileInfo>(data);
  88. var accessFileCount = dataObj.CountTheDownLoadDataItem();
  89. _fileCount = accessFileCount;
  90. fileName = String.Join("+",dataObj.SubFolders.ToArray())+DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss");
  91. _destnationName =Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop),fileName+".zip");
  92. _downloadFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,fileName);
  93. if (!Directory.Exists(_downloadFolder))
  94. {
  95. Directory.CreateDirectory(_downloadFolder);
  96. }
  97. Task.Run(() =>
  98. {
  99. try
  100. {
  101. DoExport(dataObj);
  102. }
  103. finally {
  104. }
  105. });
  106. return true;
  107. }
  108. private void DoExport(ExportRemedicalZipFileInfo exportRemedicalZipFileInfo)
  109. {
  110. var subFolders = exportRemedicalZipFileInfo.SubFolders;
  111. _cancelTokenSource = new CancellationTokenSource();
  112. _cancelToken = _cancelTokenSource.Token;
  113. _fileFinishCount = 0;
  114. ExportStatus = ExportStatus.Downloading;
  115. //下载报告
  116. Task.Run(async () => {
  117. if (exportRemedicalZipFileInfo.ExportItems.Contains(0))
  118. {
  119. var reportPath = exportRemedicalZipFileInfo.ExportItems.Count>1?
  120. Path.Combine(_downloadFolder, exportRemedicalZipFileInfo.SubFolders[0]):_downloadFolder;
  121. if (!Directory.Exists(reportPath))
  122. {
  123. Directory.CreateDirectory(reportPath);
  124. }
  125. var reports = exportRemedicalZipFileInfo.ReportList;
  126. foreach (var c in reports)
  127. {
  128. var patientPath = Path.Combine(reportPath, c.PatientName);
  129. if (!Directory.Exists(patientPath))
  130. {
  131. patientPath = patientPath.Replace("*", "");
  132. Directory.CreateDirectory(patientPath);
  133. if (c.ReportItemList.Count == 0)
  134. {
  135. var fileName = Path.Combine(patientPath, "nodata.txt");
  136. File.WriteAllText(fileName, "nodata");
  137. return;
  138. }
  139. }
  140. foreach (var d in c.ReportItemList)
  141. {
  142. if (_cancelToken.IsCancellationRequested)
  143. {
  144. break;
  145. }
  146. var bytes = await HttpHelper.httpClient.GetByteArrayAsync(d.FileToken, _cancelToken);
  147. var fileName = Path.Combine(patientPath, GetFileNameFromToken(d.FileToken));
  148. try
  149. {
  150. await File.WriteAllBytesAsync(fileName, bytes);
  151. }
  152. catch(Exception ex)
  153. {
  154. Logger.WriteShellLog(ex.ToString());
  155. }
  156. finally {
  157. _fileFinishCount++;
  158. }
  159. }
  160. }
  161. }
  162. });
  163. //下载图像
  164. Task.Run(async () =>
  165. {
  166. if (exportRemedicalZipFileInfo.ExportItems.Contains(2))
  167. {
  168. var imagePath = exportRemedicalZipFileInfo.ExportItems.Count > 1 ? Path.Combine(_downloadFolder, exportRemedicalZipFileInfo.SubFolders[1])
  169. :_downloadFolder;
  170. if (!Directory.Exists(imagePath))
  171. {
  172. Directory.CreateDirectory(imagePath);
  173. }
  174. var remedicalData = exportRemedicalZipFileInfo.RemedicalList;
  175. foreach (var c in remedicalData)
  176. {
  177. var patientPath = Path.Combine(imagePath, c.PatientName);
  178. if (!Directory.Exists(patientPath))
  179. {
  180. patientPath = patientPath.Replace("*", "");
  181. Directory.CreateDirectory(patientPath);
  182. if (c.RemedicalItemList.Count == 0)
  183. {
  184. var fileName = Path.Combine(patientPath, "nodata.txt");
  185. File.WriteAllText(fileName, "nodata");
  186. return;
  187. }
  188. }
  189. foreach (var d in c.RemedicalItemList)
  190. {
  191. if (_cancelToken.IsCancellationRequested)
  192. {
  193. break;
  194. }
  195. var bytes = await HttpHelper.httpClient.GetByteArrayAsync(d.FileToken, _cancelToken);
  196. var fileName = Path.Combine(patientPath, GetFileNameFromToken(d.FileToken));
  197. try
  198. {
  199. await File.WriteAllBytesAsync(fileName, bytes);
  200. var pathDest = Path.Combine(patientPath, GetFileNameWithoutExt(d.FileToken));
  201. var converter = new VideoFFmpegHelper(fileName);
  202. converter.ConvertVidToMpeg4(pathDest);
  203. converter.Dispose();
  204. File.Delete(fileName);
  205. }
  206. catch (Exception ex)
  207. {
  208. Logger.WriteShellLog(ex.ToString());
  209. }
  210. finally
  211. {
  212. _fileFinishCount++;
  213. }
  214. }
  215. }
  216. }
  217. });
  218. //刷新进度条
  219. Task.Run(() =>
  220. {
  221. if (_fileCount > 0)
  222. {
  223. while (ExportStatus != ExportStatus.Finished)
  224. {
  225. Thread.Sleep(1000);
  226. ExportStatus = _fileFinishCount == _fileCount ? ExportStatus.Packaging : ExportStatus.Downloading;
  227. }
  228. }
  229. else {
  230. Thread.Sleep(2000);
  231. ExportStatus = ExportStatus.Packaging;
  232. }
  233. });
  234. }
  235. private string GetFileNameFromToken(string fileToken)
  236. {
  237. string[] fragments = fileToken.Split('/');
  238. string lastFragment = fragments.Last();
  239. return lastFragment;
  240. }
  241. private string GetFileNameWithoutExt(string fileToken)
  242. {
  243. string[] fragments = fileToken.Split('/');
  244. string lastFragment = fragments.Last();
  245. return lastFragment.Split('.')[0];
  246. }
  247. public bool SetBytesToExport(string fileBinary, string fileName)
  248. {
  249. try{
  250. var file = Convert.FromBase64String(fileBinary);
  251. if (file.Length > 0)
  252. {//转换后pdf存放的路径
  253. ExportToNative(fileName,file);
  254. return true;
  255. }
  256. else
  257. {
  258. return false;
  259. }
  260. return true;
  261. }
  262. catch (Exception)
  263. {
  264. return false;
  265. }
  266. }
  267. private void DeleteTheTemps(String folder)
  268. {
  269. try
  270. {
  271. if (!Directory.Exists(folder))
  272. {
  273. return;
  274. }
  275. var files = Directory.GetFiles(folder);
  276. foreach (var c in files)
  277. {
  278. File.Delete(c);
  279. }
  280. var directorys = Directory.GetDirectories(folder);
  281. foreach (var d in directorys)
  282. {
  283. DeleteTheTemps(d);
  284. }
  285. if (Directory.GetFiles(folder).Length <= 0 && Directory.GetDirectories(folder).Length <= 0)
  286. {
  287. Directory.Delete(folder);
  288. }
  289. }
  290. catch(Exception ex) {
  291. FFmpegService.ForceCloseFFmpegIfStillAlive();
  292. DeleteTheTemps(_downloadFolder);
  293. }
  294. }
  295. private void ExportToNative(string fileName, byte[] file)
  296. {
  297. Task.Run(async () => {
  298. var filePath = await SaveFile(fileName);
  299. if (string.IsNullOrEmpty(filePath))
  300. {
  301. return;
  302. }
  303. var writer = new BinaryWriter(File.Open(filePath, FileMode.CreateNew));
  304. writer.Write(file);
  305. writer.Close();
  306. });
  307. }
  308. private async Task<string> SaveFile(string fileName)
  309. {
  310. //用户自由选择指定路径保存文件
  311. var savedialog = new SaveFileDialog();
  312. savedialog.Title = "";
  313. savedialog.InitialFileName = fileName;
  314. var fileExportedPath = await savedialog.ShowAsync(AppManager.ParentWindow);
  315. if (string.IsNullOrEmpty(fileExportedPath))
  316. {
  317. return AppDomain.CurrentDomain.BaseDirectory;
  318. }
  319. return fileExportedPath;
  320. }
  321. }
  322. }