StorageService.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. using System;
  2. using System.IO;
  3. using System.IO.Abstractions;
  4. using System.Security.Principal;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using BO.AppServer.Business.Exceptions;
  8. using BO.AppServer.Data.Entity;
  9. using BO.AppServer.Data.Repository;
  10. using BO.AppServer.Metadata.Enums;
  11. using Microsoft.Extensions.Logging;
  12. using Microsoft.Extensions.Options;
  13. using Quadarax.Foundation.Core.Business;
  14. using Quadarax.Foundation.Core.Exceptions;
  15. using Quadarax.Foundation.Core.Value.Extensions;
  16. namespace BO.AppServer.Business.Services
  17. {
  18. public class StorageService : AbstractService
  19. {
  20. #region *** Private fields ***
  21. private IFileSystem _fileSystem;
  22. private IOptions<Configuration.Configuration> _config;
  23. private ArtifactRepo _repoArtifact;
  24. #endregion
  25. #region *** Constructors ***
  26. public StorageService(ArtifactRepo repoArtifact,
  27. IOptions<Configuration.Configuration> config,
  28. IFileSystem fileSystem,
  29. IPrincipal currentPrincipal,
  30. ILoggerFactory logger) : base(currentPrincipal, logger)
  31. {
  32. _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem));
  33. _config = config ?? throw new ArgumentNullException(nameof(config));
  34. _repoArtifact = repoArtifact ?? throw new ArgumentNullException(nameof(repoArtifact));
  35. if (!_fileSystem.Directory.Exists(_config.Value.System.Storage.InputPath.EnsurePathNonBackslash()))
  36. {
  37. _fileSystem.Directory.CreateDirectory(_config.Value.System.Storage.InputPath.EnsurePathNonBackslash());
  38. Log.LogInformation($"Storage Input directory '{_config.Value.System.Storage.InputPath.EnsurePathNonBackslash()}' created.");
  39. }
  40. else
  41. Log.LogInformation($"Storage Input directory '{_config.Value.System.Storage.InputPath.EnsurePathNonBackslash()}' verified.");
  42. if (!_fileSystem.Directory.Exists(_config.Value.System.Storage.OutputPath.EnsurePathNonBackslash()))
  43. {
  44. _fileSystem.Directory.CreateDirectory(_config.Value.System.Storage.OutputPath.EnsurePathNonBackslash());
  45. Log.LogInformation($"Storage Output directory '{_config.Value.System.Storage.OutputPath.EnsurePathNonBackslash()}' created.");
  46. }
  47. else
  48. Log.LogInformation($"Storage Input directory '{_config.Value.System.Storage.InputPath.EnsurePathNonBackslash()}' verified.");
  49. }
  50. #endregion
  51. #region *** Public Operations ***
  52. public async Task<long> PushContentAsync(long artifactId, Stream fileData)
  53. {
  54. var artifact = _repoArtifact.Get(artifactId);
  55. if (artifact == null)
  56. {
  57. var exc = new EntityNotExistsException(typeof(Artifact),nameof(Artifact.Id), artifactId);
  58. Log.LogWarning(exc.Message);
  59. throw exc;
  60. }
  61. var documentId = artifact.Metadocument.Id;
  62. var workspaceId = artifact.Metadocument.Structure.WorkspaceId;
  63. var fileName = GetFileName(artifactId, artifact.Name, artifact.Extension);
  64. var artType = (ArtifactTypeEnum)artifact.Type;
  65. var fullFileName = EnureDirectory(workspaceId, documentId, artType) + _fileSystem.Path.DirectorySeparatorChar + fileName;
  66. long size;
  67. await using (var fs = _fileSystem.File.Create(fullFileName, _config.Value.System.Storage.IoBufferSize, FileOptions.Asynchronous))
  68. {
  69. fileData.Position = 0;
  70. await fileData.CopyToAsync(fs, _config.Value.System.Storage.IoBufferSize);
  71. await fs.FlushAsync();
  72. size = fs.Length;
  73. fs.Close();
  74. }
  75. return size;
  76. }
  77. public async Task<Tuple<Stream, long>> PopContentAsync(long artifactId)
  78. {
  79. var artifact = _repoArtifact.Get(artifactId);
  80. if (artifact == null)
  81. {
  82. var exc = new EntityNotExistsException(typeof(Artifact),nameof(Artifact.Id), artifactId);
  83. Log.LogWarning(exc.Message);
  84. throw exc;
  85. }
  86. var documentId = artifact.Metadocument.Id;
  87. var workspaceId = artifact.Metadocument.Structure.WorkspaceId;
  88. var fileName = GetFileName(artifactId, artifact.Name, artifact.Extension);
  89. var artType = (ArtifactTypeEnum)artifact.Type;
  90. var fullFileName = EnureDirectory(workspaceId, documentId, artType) + _fileSystem.Path.DirectorySeparatorChar + fileName;
  91. if (!_fileSystem.File.Exists(fullFileName))
  92. {
  93. var message = $"Content for artifact '{fullFileName}' [{artifactId}] not found!";
  94. Log.LogWarning(message);
  95. throw new CodeException(1300, message);
  96. }
  97. var buffer = new byte[_config.Value.System.Storage.IoBufferSize];
  98. //var outputStream = new MemoryStream(buffer);
  99. var outputStream = new MemoryStream();
  100. await using (var fs = _fileSystem.File.OpenRead(fullFileName))
  101. {
  102. //await fs.CopyToAsync(outputStream, _config.Value.System.Storage.IoBufferSize);
  103. await fs.CopyToAsync(outputStream);
  104. await outputStream.FlushAsync();
  105. fs.Close();
  106. }
  107. outputStream.Seek(0, SeekOrigin.Begin);
  108. return new Tuple<Stream, long>(outputStream, outputStream.Length);
  109. }
  110. public async Task<bool> DeleteContent(long artifactId)
  111. {
  112. var artifact = _repoArtifact.Get(artifactId);
  113. if (artifact == null)
  114. {
  115. var exc = new EntityNotExistsException(typeof(Artifact),nameof(Artifact.Id), artifactId);
  116. Log.LogWarning(exc.Message);
  117. throw exc;
  118. }
  119. var documentId = artifact.Metadocument.Id;
  120. var workspaceId = artifact.Metadocument.Structure.WorkspaceId;
  121. var fileName = GetFileName(artifactId, artifact.Name, artifact.Extension);
  122. var artType = (ArtifactTypeEnum)artifact.Type;
  123. var fullFileName = EnureDirectory(workspaceId, documentId, artType) + _fileSystem.Path.DirectorySeparatorChar + fileName;
  124. if (!_fileSystem.File.Exists(fullFileName))
  125. {
  126. var message = $"Content for artifact '{fullFileName}' [{artifactId}] not found for delete!";
  127. Log.LogInformation(message);
  128. return false;
  129. }
  130. _fileSystem.File.Delete(fullFileName);
  131. return true;
  132. }
  133. #endregion
  134. #region *** Private Operations ***
  135. private string EnureDirectory(long workspaceId, long documentId, ArtifactTypeEnum type)
  136. {
  137. var dirName = GetDirectoryName(workspaceId, documentId, type);
  138. if (!_fileSystem.Directory.Exists(dirName))
  139. {
  140. _fileSystem.Directory.CreateDirectory(dirName);
  141. Log.LogInformation($"Storage document directory '{dirName}' created.");
  142. }
  143. return dirName;
  144. }
  145. private string GetDirectoryName(long workspaceId, long documentId, ArtifactTypeEnum type)
  146. {
  147. var sb = new StringBuilder();
  148. sb.Append(type == ArtifactTypeEnum.Input ? _config.Value.System.Storage.InputPath.EnsurePathNonBackslash() : _config.Value.System.Storage.OutputPath.EnsurePathNonBackslash()).Append(_fileSystem.Path.DirectorySeparatorChar);
  149. sb.Append(workspaceId).Append(_fileSystem.Path.DirectorySeparatorChar);
  150. sb.Append(documentId);
  151. return sb.ToString();
  152. }
  153. private string GetFileName(long artifactId, string fileNameWoExtension, string extension)
  154. {
  155. var sb = new StringBuilder();
  156. sb.Append(fileNameWoExtension).Append(".");
  157. sb.Append(artifactId).Append(".");
  158. sb.Append(extension);
  159. return sb.ToString();
  160. }
  161. #endregion
  162. }
  163. }