StorageService.cs 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  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. await using (var fs = _fileSystem.File.OpenRead(fullFileName))
  100. {
  101. await fs.CopyToAsync(outputStream, _config.Value.System.Storage.IoBufferSize);
  102. fs.Close();
  103. }
  104. return new Tuple<Stream, long>(outputStream, outputStream.Length);
  105. }
  106. public async Task<bool> DeleteContent(long artifactId)
  107. {
  108. var artifact = _repoArtifact.Get(artifactId);
  109. if (artifact == null)
  110. {
  111. var exc = new EntityNotExistsException(typeof(Artifact),nameof(Artifact.Id), artifactId);
  112. Log.LogWarning(exc.Message);
  113. throw exc;
  114. }
  115. var documentId = artifact.Metadocument.Id;
  116. var workspaceId = artifact.Metadocument.Structure.WorkspaceId;
  117. var fileName = GetFileName(artifactId, artifact.Name, artifact.Extension);
  118. var artType = (ArtifactTypeEnum)artifact.Type;
  119. var fullFileName = EnureDirectory(workspaceId, documentId, artType) + _fileSystem.Path.DirectorySeparatorChar + fileName;
  120. if (!_fileSystem.File.Exists(fullFileName))
  121. {
  122. var message = $"Content for artifact '{fullFileName}' [{artifactId}] not found for delete!";
  123. Log.LogInformation(message);
  124. return false;
  125. }
  126. _fileSystem.File.Delete(fullFileName);
  127. return true;
  128. }
  129. #endregion
  130. #region *** Private Operations ***
  131. private string EnureDirectory(long workspaceId, long documentId, ArtifactTypeEnum type)
  132. {
  133. var dirName = GetDirectoryName(workspaceId, documentId, type);
  134. if (!_fileSystem.Directory.Exists(dirName))
  135. {
  136. _fileSystem.Directory.CreateDirectory(dirName);
  137. Log.LogInformation($"Storage document directory '{dirName}' created.");
  138. }
  139. return dirName;
  140. }
  141. private string GetDirectoryName(long workspaceId, long documentId, ArtifactTypeEnum type)
  142. {
  143. var sb = new StringBuilder();
  144. sb.Append(type == ArtifactTypeEnum.Input ? _config.Value.System.Storage.InputPath.EnsurePathNonBackslash() : _config.Value.System.Storage.OutputPath.EnsurePathNonBackslash()).Append(_fileSystem.Path.DirectorySeparatorChar);
  145. sb.Append(workspaceId).Append(_fileSystem.Path.DirectorySeparatorChar);
  146. sb.Append(documentId);
  147. return sb.ToString();
  148. }
  149. private string GetFileName(long artifactId, string fileNameWoExtension, string extension)
  150. {
  151. var sb = new StringBuilder();
  152. sb.Append(fileNameWoExtension).Append(".");
  153. sb.Append(artifactId).Append(".");
  154. sb.Append(extension);
  155. return sb.ToString();
  156. }
  157. #endregion
  158. }
  159. }