diff --git a/aspnet-core/LINGYUN.MicroService.sln b/aspnet-core/LINGYUN.MicroService.sln index 2b9912278..765497dde 100644 --- a/aspnet-core/LINGYUN.MicroService.sln +++ b/aspnet-core/LINGYUN.MicroService.sln @@ -185,13 +185,25 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.EntityFramework EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "identity", "identity", "{52B5D4F7-237B-4E0A-A167-68442164F70A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Identity.Application.Contracts", "modules\identity\LINGYUN.Abp.Identity.Application.Contracts\LINGYUN.Abp.Identity.Application.Contracts.csproj", "{F19C8B0F-A332-4190-9ABE-95790E0AE864}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Application.Contracts", "modules\identity\LINGYUN.Abp.Identity.Application.Contracts\LINGYUN.Abp.Identity.Application.Contracts.csproj", "{F19C8B0F-A332-4190-9ABE-95790E0AE864}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Identity.Application", "modules\identity\LINGYUN.Abp.Identity.Application\LINGYUN.Abp.Identity.Application.csproj", "{BB1B831F-4AC4-4DE5-A879-D5FC5B1CA9DA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Application", "modules\identity\LINGYUN.Abp.Identity.Application\LINGYUN.Abp.Identity.Application.csproj", "{BB1B831F-4AC4-4DE5-A879-D5FC5B1CA9DA}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Identity.HttpApi", "modules\identity\LINGYUN.Abp.Identity.HttpApi\LINGYUN.Abp.Identity.HttpApi.csproj", "{72DCA4CF-8B95-47C9-B02A-2671953B7987}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.HttpApi", "modules\identity\LINGYUN.Abp.Identity.HttpApi\LINGYUN.Abp.Identity.HttpApi.csproj", "{72DCA4CF-8B95-47C9-B02A-2671953B7987}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Identity.HttpApi.Client", "modules\identity\LINGYUN.Abp.Identity.HttpApi.Client\LINGYUN.Abp.Identity.HttpApi.Client.csproj", "{7DDEAEA9-E392-469C-ACB6-908C5BAD669E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.HttpApi.Client", "modules\identity\LINGYUN.Abp.Identity.HttpApi.Client\LINGYUN.Abp.Identity.HttpApi.Client.csproj", "{7DDEAEA9-E392-469C-ACB6-908C5BAD669E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "file-management", "file-management", "{B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.FileManagement.Application", "modules\file-management\LINGYUN.Abp.FileManagement.Application\LINGYUN.Abp.FileManagement.Application.csproj", "{F3D50E3E-34D2-48C1-AB0D-ADCF92DC07D0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.FileManagement.Application.Contracts", "modules\file-management\LINGYUN.Abp.FileManagement.Application.Contracts\LINGYUN.Abp.FileManagement.Application.Contracts.csproj", "{86A67B8C-EFA0-4103-B60F-312F07C15A7A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.FileManagement.HttpApi", "modules\file-management\LINGYUN.Abp.FileManagement.HttpApi\LINGYUN.Abp.FileManagement.HttpApi.csproj", "{854E1A42-FEA4-420E-9E83-0A39EE03F1ED}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.FileManagement.Domain.Shared", "modules\file-management\LINGYUN.Abp.FileManagement.Domain.Shared\LINGYUN.Abp.FileManagement.Domain.Shared.csproj", "{21FCEF89-9A3F-476E-833A-A9C2131B2AE6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.FileManagement.Domain", "modules\file-management\LINGYUN.Abp.FileManagement.Domain\LINGYUN.Abp.FileManagement.Domain.csproj", "{14ECCFD6-2DC1-4124-BE26-15E8D28E3E90}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -511,6 +523,26 @@ Global {7DDEAEA9-E392-469C-ACB6-908C5BAD669E}.Debug|Any CPU.Build.0 = Debug|Any CPU {7DDEAEA9-E392-469C-ACB6-908C5BAD669E}.Release|Any CPU.ActiveCfg = Release|Any CPU {7DDEAEA9-E392-469C-ACB6-908C5BAD669E}.Release|Any CPU.Build.0 = Release|Any CPU + {F3D50E3E-34D2-48C1-AB0D-ADCF92DC07D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F3D50E3E-34D2-48C1-AB0D-ADCF92DC07D0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F3D50E3E-34D2-48C1-AB0D-ADCF92DC07D0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F3D50E3E-34D2-48C1-AB0D-ADCF92DC07D0}.Release|Any CPU.Build.0 = Release|Any CPU + {86A67B8C-EFA0-4103-B60F-312F07C15A7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {86A67B8C-EFA0-4103-B60F-312F07C15A7A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {86A67B8C-EFA0-4103-B60F-312F07C15A7A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {86A67B8C-EFA0-4103-B60F-312F07C15A7A}.Release|Any CPU.Build.0 = Release|Any CPU + {854E1A42-FEA4-420E-9E83-0A39EE03F1ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {854E1A42-FEA4-420E-9E83-0A39EE03F1ED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {854E1A42-FEA4-420E-9E83-0A39EE03F1ED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {854E1A42-FEA4-420E-9E83-0A39EE03F1ED}.Release|Any CPU.Build.0 = Release|Any CPU + {21FCEF89-9A3F-476E-833A-A9C2131B2AE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {21FCEF89-9A3F-476E-833A-A9C2131B2AE6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {21FCEF89-9A3F-476E-833A-A9C2131B2AE6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {21FCEF89-9A3F-476E-833A-A9C2131B2AE6}.Release|Any CPU.Build.0 = Release|Any CPU + {14ECCFD6-2DC1-4124-BE26-15E8D28E3E90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {14ECCFD6-2DC1-4124-BE26-15E8D28E3E90}.Debug|Any CPU.Build.0 = Debug|Any CPU + {14ECCFD6-2DC1-4124-BE26-15E8D28E3E90}.Release|Any CPU.ActiveCfg = Release|Any CPU + {14ECCFD6-2DC1-4124-BE26-15E8D28E3E90}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -608,6 +640,12 @@ Global {BB1B831F-4AC4-4DE5-A879-D5FC5B1CA9DA} = {52B5D4F7-237B-4E0A-A167-68442164F70A} {72DCA4CF-8B95-47C9-B02A-2671953B7987} = {52B5D4F7-237B-4E0A-A167-68442164F70A} {7DDEAEA9-E392-469C-ACB6-908C5BAD669E} = {52B5D4F7-237B-4E0A-A167-68442164F70A} + {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {F3D50E3E-34D2-48C1-AB0D-ADCF92DC07D0} = {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6} + {86A67B8C-EFA0-4103-B60F-312F07C15A7A} = {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6} + {854E1A42-FEA4-420E-9E83-0A39EE03F1ED} = {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6} + {21FCEF89-9A3F-476E-833A-A9C2131B2AE6} = {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6} + {14ECCFD6-2DC1-4124-BE26-15E8D28E3E90} = {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C95FDF91-16F2-4A8B-A4BE-0E62D1B66718} diff --git a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN/Abp/Account/AbpAccountDomainModule.cs b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN/Abp/Account/AbpAccountDomainModule.cs index 38693428c..26100b96d 100644 --- a/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN/Abp/Account/AbpAccountDomainModule.cs +++ b/aspnet-core/modules/account/LINGYUN.Abp.Account.Domain/LINGYUN/Abp/Account/AbpAccountDomainModule.cs @@ -1,4 +1,6 @@ using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Domain.Entities.Events.Distributed; +using Volo.Abp.Identity; using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Abp.VirtualFileSystem; @@ -21,6 +23,11 @@ namespace LINGYUN.Abp.Account .Get() .AddVirtualJson("/LINGYUN/Abp/Account/Localization/Resources"); }); + + Configure(options => + { + options.AutoEventSelectors.AddNamespace("Volo.Abp.Identity"); + }); } } } diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN.Abp.FileManagement.Application.Contracts.csproj b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN.Abp.FileManagement.Application.Contracts.csproj new file mode 100644 index 000000000..382a43c07 --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN.Abp.FileManagement.Application.Contracts.csproj @@ -0,0 +1,16 @@ + + + + netstandard2.0 + + + + + + + + + + + + diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/AbpFileManagementApplicationContractsModule.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/AbpFileManagementApplicationContractsModule.cs new file mode 100644 index 000000000..891ac26a2 --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/AbpFileManagementApplicationContractsModule.cs @@ -0,0 +1,11 @@ +using Volo.Abp.Application; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.FileManagement +{ + [DependsOn( + typeof(AbpDddApplicationModule))] + public class AbpFileManagementApplicationContractsModule : AbpModule + { + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileCopyOrMoveDto.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileCopyOrMoveDto.cs new file mode 100644 index 000000000..bbda957fe --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileCopyOrMoveDto.cs @@ -0,0 +1,22 @@ +using System.ComponentModel.DataAnnotations; + +namespace LINGYUN.Abp.FileManagement +{ + public class FileCopyOrMoveDto + { + [Required] + [StringLength(255)] + public string Path { get; set; } + + [Required] + [StringLength(255)] + public string Name { get; set; } + + [Required] + [StringLength(255)] + public string ToPath { get; set; } + + [StringLength(255)] + public string ToName { get; set; } + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileCreateDto.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileCreateDto.cs new file mode 100644 index 000000000..5a5096e58 --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileCreateDto.cs @@ -0,0 +1,39 @@ +using System.ComponentModel.DataAnnotations; +using Volo.Abp.Auditing; + +namespace LINGYUN.Abp.FileManagement +{ + public class FileCreateDto + { + /// + /// 文件名 + /// + [Required] + [StringLength(255)] + public string Name { get; set; } + /// + /// 文件路径 + /// + [StringLength(255)] + public string Path { get; set; } + /// + /// 文件数据,前端无需传递此参数,由控制器传递 + /// + [DisableAuditing] + public byte[] Data { get; set; } + /// + /// 当前字节数 + /// + [Required] + public int CurrentByte { get; set; } + /// + /// 最大字节数 + /// + [Required] + public int TotalByte { get; set; } + /// + /// 是否覆盖文件 + /// + public bool Rewrite { get; set; } = false; + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileDeleteDto.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileDeleteDto.cs new file mode 100644 index 000000000..f74c4d823 --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileDeleteDto.cs @@ -0,0 +1,15 @@ +using System.ComponentModel.DataAnnotations; + +namespace LINGYUN.Abp.FileManagement +{ + public class FileDeleteDto + { + [Required] + [StringLength(255)] + public string Path { get; set; } + + [Required] + [StringLength(255)] + public string Name { get; set; } + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileSystemDto.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileSystemDto.cs new file mode 100644 index 000000000..5efdebc45 --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileSystemDto.cs @@ -0,0 +1,14 @@ +using System; + +namespace LINGYUN.Abp.FileManagement +{ + public class FileSystemDto + { + public FileSystemType Type { get; set; } + public string Name { get; set; } + public string Parent { get; set; } + public long? Size { get; set; } + public DateTime CreationTime { get; set; } + public DateTime? LastModificationTime { get; set; } + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileSystemGetDto.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileSystemGetDto.cs new file mode 100644 index 000000000..421ae1803 --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileSystemGetDto.cs @@ -0,0 +1,15 @@ +using System.ComponentModel.DataAnnotations; + +namespace LINGYUN.Abp.FileManagement +{ + public class FileSystemGetDto + { + [Required] + [StringLength(255)] + public string Path { get; set; } + + [Required] + [StringLength(255)] + public string Name { get; set; } + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileSystemType.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileSystemType.cs new file mode 100644 index 000000000..ecbcd214d --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileSystemType.cs @@ -0,0 +1,8 @@ +namespace LINGYUN.Abp.FileManagement +{ + public enum FileSystemType + { + Folder = 0, + File = 1 + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileSystemUpdateDto.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileSystemUpdateDto.cs new file mode 100644 index 000000000..3f4193bf4 --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileSystemUpdateDto.cs @@ -0,0 +1,11 @@ +using System.ComponentModel.DataAnnotations; + +namespace LINGYUN.Abp.FileManagement +{ + public class FileSystemUpdateDto + { + [Required] + [StringLength(255)] + public string NewName { get; set; } + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FolderCopyDto.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FolderCopyDto.cs new file mode 100644 index 000000000..ada1ca9a5 --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FolderCopyDto.cs @@ -0,0 +1,11 @@ +using System.ComponentModel.DataAnnotations; + +namespace LINGYUN.Abp.FileManagement +{ + public class FolderCopyDto + { + [Required] + [StringLength(255)] + public string CopyToPath { get; set; } + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FolderCreateDto.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FolderCreateDto.cs new file mode 100644 index 000000000..9d2c09d93 --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FolderCreateDto.cs @@ -0,0 +1,13 @@ +using System.ComponentModel.DataAnnotations; + +namespace LINGYUN.Abp.FileManagement +{ + public class FolderCreateDto + { + [Required] + [StringLength(255)] + public string Path { get; set; } + + public string Parent { get; set; } + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FolderMoveDto.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FolderMoveDto.cs new file mode 100644 index 000000000..760b79ad8 --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FolderMoveDto.cs @@ -0,0 +1,11 @@ +using System.ComponentModel.DataAnnotations; + +namespace LINGYUN.Abp.FileManagement +{ + public class FolderMoveDto + { + [Required] + [StringLength(255)] + public string MoveToPath { get; set; } + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/GetFileSystemListDto.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/GetFileSystemListDto.cs new file mode 100644 index 000000000..29b4f02cb --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/GetFileSystemListDto.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations; +using Volo.Abp.Application.Dtos; + +namespace LINGYUN.Abp.FileManagement +{ + public class GetFileSystemListDto : PagedAndSortedResultRequestDto + { + // TODO: Windows最大路径长度,超过了貌似也无效了吧 + [StringLength(255)] + public string Parent { get; set; } + + public string Filter { get; set; } + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/IFileSystemAppService.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/IFileSystemAppService.cs new file mode 100644 index 000000000..4a5955161 --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/IFileSystemAppService.cs @@ -0,0 +1,35 @@ +using System.ComponentModel.DataAnnotations; +using System.IO; +using System.Threading.Tasks; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; + +namespace LINGYUN.Abp.FileManagement +{ + public interface IFileSystemAppService : IApplicationService + { + Task GetAsync(FileSystemGetDto input); + + Task> GetListAsync(GetFileSystemListDto input); + + Task CreateFolderAsync(FolderCreateDto input); + + Task UpdateAsync([Required, StringLength(255)] string name, FileSystemUpdateDto input); + + Task DeleteFolderAsync([Required, StringLength(255)] string path); + + Task MoveFolderAsync([Required, StringLength(255)] string path, FolderMoveDto input); + + Task CopyFolderAsync([Required, StringLength(255)] string path, FolderCopyDto input); + + Task CreateFileAsync(FileCreateDto input); + + Task DeleteFileAsync(FileDeleteDto input); + + Task MoveFileAsync(FileCopyOrMoveDto input); + + Task CopyFileAsync(FileCopyOrMoveDto input); + + Task DownloadFileAsync(FileSystemGetDto input); + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/Permissions/AbpFileManagementPermissionDefinitionProvider.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/Permissions/AbpFileManagementPermissionDefinitionProvider.cs new file mode 100644 index 000000000..1c1ac9f1a --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/Permissions/AbpFileManagementPermissionDefinitionProvider.cs @@ -0,0 +1,34 @@ +using LINGYUN.Abp.FileManagement.Localization; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Localization; + +namespace LINGYUN.Abp.FileManagement.Permissions +{ + public class AbpFileManagementPermissionDefinitionProvider : PermissionDefinitionProvider + { + public override void Define(IPermissionDefinitionContext context) + { + var fileManagement = context.AddGroup(AbpFileManagementPermissions.GroupName, L("Permission:FileManagement")); + + var fileSystem = fileManagement.AddPermission(AbpFileManagementPermissions.FileSystem.Default, L("Permission:FileSystem")); + fileSystem.AddChild(AbpFileManagementPermissions.FileSystem.Create, L("Permission:CreateFolder")); + fileSystem.AddChild(AbpFileManagementPermissions.FileSystem.Delete, L("Permission:DeleteFolder")); + fileSystem.AddChild(AbpFileManagementPermissions.FileSystem.Update, L("Permission:UpdateFolder")); + fileSystem.AddChild(AbpFileManagementPermissions.FileSystem.Copy, L("Permission:CopyFolder")); + fileSystem.AddChild(AbpFileManagementPermissions.FileSystem.Move, L("Permission:MoveFolder")); + + var fileManager = fileSystem.AddChild(AbpFileManagementPermissions.FileSystem.FileManager.Default, L("Permission:FileManager")); + fileManager.AddChild(AbpFileManagementPermissions.FileSystem.FileManager.Create, L("Permission:AppendFile")); + fileManager.AddChild(AbpFileManagementPermissions.FileSystem.FileManager.Update, L("Permission:UpdateFile")); + fileManager.AddChild(AbpFileManagementPermissions.FileSystem.FileManager.Delete, L("Permission:DeleteFile")); + fileManager.AddChild(AbpFileManagementPermissions.FileSystem.FileManager.Copy, L("Permission:CopyFile")); + fileManager.AddChild(AbpFileManagementPermissions.FileSystem.FileManager.Move, L("Permission:MoveFile")); + fileManager.AddChild(AbpFileManagementPermissions.FileSystem.FileManager.Download, L("Permission:DownloadFile")); + } + + private static LocalizableString L(string name) + { + return LocalizableString.Create(name); + } + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/Permissions/AbpFileManagementPermissions.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/Permissions/AbpFileManagementPermissions.cs new file mode 100644 index 000000000..0b415358f --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/Permissions/AbpFileManagementPermissions.cs @@ -0,0 +1,44 @@ +namespace LINGYUN.Abp.FileManagement.Permissions +{ + public class AbpFileManagementPermissions + { + public const string GroupName = "Abp.FileManagement"; + + /// + /// 文件系统 + /// + public class FileSystem + { + public const string Default = GroupName + ".FileSystem"; + + public const string Create = Default + ".Create"; + + public const string Delete = Default + ".Delete"; + + public const string Update = Default + ".Update"; + + public const string Copy = Default + ".Copy"; + + public const string Move = Default + ".Move"; + /// + /// 文件管理 + /// + public class FileManager + { + public const string Default = FileSystem.Default + ".FileManager"; + + public const string Create = Default + ".Create"; + + public const string Copy = Default + ".Copy"; + + public const string Delete = Default + ".Delete"; + + public const string Update = Default + ".Update"; + + public const string Move = Default + ".Move"; + + public const string Download = Default + ".Download"; + } + } + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application/LINGYUN.Abp.FileManagement.Application.csproj b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application/LINGYUN.Abp.FileManagement.Application.csproj new file mode 100644 index 000000000..3855f470f --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application/LINGYUN.Abp.FileManagement.Application.csproj @@ -0,0 +1,13 @@ + + + + netstandard2.0 + + + + + + + + + diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application/LINGYUN/Abp/FileManagement/AbpFileManagementApplicationModule.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application/LINGYUN/Abp/FileManagement/AbpFileManagementApplicationModule.cs new file mode 100644 index 000000000..4d52281a1 --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application/LINGYUN/Abp/FileManagement/AbpFileManagementApplicationModule.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.FileManagement +{ + [DependsOn( + typeof(AbpFileManagementDomainModule), + typeof(AbpFileManagementApplicationContractsModule))] + public class AbpFileManagementApplicationModule : AbpModule + { + + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application/LINGYUN/Abp/FileManagement/FileManagementApplicationServiceBase.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application/LINGYUN/Abp/FileManagement/FileManagementApplicationServiceBase.cs new file mode 100644 index 000000000..5b0dfbc85 --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application/LINGYUN/Abp/FileManagement/FileManagementApplicationServiceBase.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Volo.Abp.Application.Services; + +namespace LINGYUN.Abp.FileManagement +{ + public class FileManagementApplicationServiceBase : ApplicationService + { + protected FileManagementApplicationServiceBase() + { + + } + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application/LINGYUN/Abp/FileManagement/FileSystemAppService.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application/LINGYUN/Abp/FileManagement/FileSystemAppService.cs new file mode 100644 index 000000000..1d2c82838 --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application/LINGYUN/Abp/FileManagement/FileSystemAppService.cs @@ -0,0 +1,392 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.Application.Dtos; +using Volo.Abp.BlobStoring; +using Volo.Abp.BlobStoring.FileSystem; + +namespace LINGYUN.Abp.FileManagement +{ + public class FileSystemAppService : FileManagementApplicationServiceBase, IFileSystemAppService + { + protected IBlobContainer BlobContainer { get; } + protected IBlobContainerConfigurationProvider BlobContainerConfigurationProvider { get; } + public FileSystemAppService( + IBlobContainer blobContainer, + IBlobContainerConfigurationProvider blobContainerConfigurationProvider) + { + BlobContainer = blobContainer; + BlobContainerConfigurationProvider = blobContainerConfigurationProvider; + } + + public virtual Task CopyFileAsync(FileCopyOrMoveDto input) + { + string fileSystemPath = GetFileSystemPath(input.Path); + var fileFullName = Path.Combine(fileSystemPath, input.Name); + if (!File.Exists(fileFullName)) + { + throw new UserFriendlyException("指定的文件不存在!"); + } + var copyToFilePath = GetFileSystemPath(input.ToPath); + var copyToFileFullName = Path.Combine(copyToFilePath, input.ToName ?? input.Name); + if (File.Exists(copyToFileFullName)) + { + throw new UserFriendlyException("指定的路径中已经有相同的文件名存在!"); + } + + File.Copy(fileFullName, copyToFileFullName); + + return Task.CompletedTask; + } + + public virtual Task CopyFolderAsync([Required, StringLength(255)] string path, FolderCopyDto input) + { + string fileSystemPath = GetFileSystemPath(path); + if (!Directory.Exists(fileSystemPath)) + { + throw new UserFriendlyException("指定目录不存在!"); + } + var copyToFilePath = GetFileSystemPath(input.CopyToPath); + if (Directory.Exists(copyToFilePath)) + { + throw new UserFriendlyException("指定的路径中已经有同名的目录存在!"); + } + + CopyDirectory(fileSystemPath, copyToFilePath); + + return Task.CompletedTask; + } + + public virtual async Task CreateFileAsync(FileCreateDto input) + { + string fileSystemPath = GetFileSystemPath(input.Path); + var fileFullName = Path.Combine(fileSystemPath, input.Name); + if (File.Exists(fileFullName) && !input.Rewrite) + { + throw new UserFriendlyException("指定的文件已经存在!"); + } + await BlobContainer.SaveAsync(input.Name, input.Data, input.Rewrite); + } + + public virtual Task CreateFolderAsync(FolderCreateDto input) + { + string fileSystemPath = GetFileSystemBashPath(); + if (!input.Parent.IsNullOrWhiteSpace()) + { + fileSystemPath = GetFileSystemPath(input.Parent); + } + var newFloderPath = Path.Combine(fileSystemPath, input.Path); + if (Directory.Exists(newFloderPath)) + { + throw new UserFriendlyException("指定目录已经存在!"); + } + Directory.CreateDirectory(newFloderPath); + + return Task.CompletedTask; + } + + public virtual Task DeleteFileAsync(FileDeleteDto input) + { + var fileSystemPath = GetFileSystemPath(input.Path); + fileSystemPath = Path.Combine(fileSystemPath, input.Name); + if (File.Exists(fileSystemPath)) + { + File.Delete(fileSystemPath); + } + return Task.CompletedTask; + } + + public virtual Task DeleteFolderAsync([Required, StringLength(255)] string path) + { + string fileSystemPath = GetFileSystemPath(path); + if (!Directory.Exists(fileSystemPath)) + { + throw new UserFriendlyException("指定目录不存在!"); + } + var fileSystemChildrenPath = Directory.GetDirectories(fileSystemPath); + if (fileSystemChildrenPath.Length > 0) + { + throw new UserFriendlyException("指定的目录不为空,不可删除此目录!"); + } + var fileSystemPathFiles = Directory.GetFiles(fileSystemPath); + if (fileSystemPathFiles.Length > 0) + { + throw new UserFriendlyException("指定的目录不为空,不可删除此目录!"); + } + Directory.Delete(fileSystemPath); + return Task.CompletedTask; + } + + public virtual async Task DownloadFileAsync(FileSystemGetDto input) + { + var fileSystemPath = GetFileSystemPath(input.Path); + fileSystemPath = Path.Combine(fileSystemPath, input.Name); + var blobName = GetFileSystemRelativePath(fileSystemPath); + + return await BlobContainer.GetAsync(blobName); + } + + public virtual Task GetAsync(FileSystemGetDto input) + { + var fileSystemPath = GetFileSystemPath(input.Path); + fileSystemPath = Path.Combine(fileSystemPath, input.Name); + if (File.Exists(fileSystemPath)) + { + var fileInfo = new FileInfo(fileSystemPath); + var fileSystem = new FileSystemDto + { + Type = FileSystemType.File, + Name = fileInfo.Name, + Size = fileInfo.Length, + CreationTime = fileInfo.CreationTime, + LastModificationTime = fileInfo.LastWriteTime + }; + if (fileInfo.Directory?.Parent != null && !fileInfo.Directory.Parent.Name.IsNullOrWhiteSpace()) + { + fileSystem.Parent = GetFileSystemRelativePath(fileInfo.Directory.Parent.FullName); + } + return Task.FromResult(fileSystem); + } + if (Directory.Exists(fileSystemPath)) + { + var directoryInfo = new DirectoryInfo(fileSystemPath); + var fileSystem = new FileSystemDto + { + Type = FileSystemType.Folder, + Name = directoryInfo.Name, + CreationTime = directoryInfo.CreationTime, + LastModificationTime = directoryInfo.LastWriteTime + }; + if (directoryInfo.Parent != null && !directoryInfo.Parent.Name.IsNullOrWhiteSpace()) + { + fileSystem.Parent = GetFileSystemRelativePath(directoryInfo.Parent.FullName); + } + return Task.FromResult(fileSystem); + } + throw new UserFriendlyException("文件或目录不存在!"); + } + + public virtual Task> GetListAsync(GetFileSystemListDto input) + { + List fileSystems = new List(); + + string fileSystemPath = GetFileSystemBashPath(); + if (!input.Parent.IsNullOrWhiteSpace()) + { + fileSystemPath = GetFileSystemPath(input.Parent); + } + var directoryInfo = new DirectoryInfo(fileSystemPath); + // 查询全部 + var fileSystemInfos = directoryInfo.GetFileSystemInfos(); + // 指定搜索条件查询目录 + FileSystemInfo[] fileSystemInfoSearchChildren;// = directoryInfo.GetDirectories(input.Filter ?? "*", SearchOption.TopDirectoryOnly); + if (!input.Filter.IsNullOrWhiteSpace()) + { + var searchPattern = $"*{input.Filter}*"; + fileSystemInfoSearchChildren = directoryInfo.GetFileSystemInfos(searchPattern); + } + else + { + fileSystemInfoSearchChildren = directoryInfo.GetFileSystemInfos(); + } + + fileSystemInfoSearchChildren = fileSystemInfoSearchChildren + .Skip((input.SkipCount - 1) * input.MaxResultCount) + .Take(input.MaxResultCount) + .ToArray(); + + foreach (var fileSystemInfo in fileSystemInfoSearchChildren) + { + var fileSystem = new FileSystemDto + { + Name = fileSystemInfo.Name, + CreationTime = fileSystemInfo.CreationTime, + LastModificationTime = fileSystemInfo.LastWriteTime, + }; + if (fileSystemInfo is FileInfo fileInfo) + { + fileSystem.Type = FileSystemType.File; + fileSystem.Size = fileInfo.Length; + if (fileInfo.Directory?.Parent != null && !fileInfo.Directory.Parent.Name.IsNullOrWhiteSpace()) + { + fileSystem.Parent = GetFileSystemRelativePath(fileInfo.Directory.Parent.FullName); + } + } + else if (fileSystemInfo is DirectoryInfo directory) + { + fileSystem.Type = FileSystemType.Folder; + if (directory.Parent != null && !directory.Parent.Name.IsNullOrWhiteSpace()) + { + fileSystem.Parent = GetFileSystemRelativePath(directory.Parent.FullName); + } + } + fileSystems.Add(fileSystem); + } + + return Task.FromResult(new PagedResultDto( + fileSystemInfos.Length, fileSystems + )); + } + + public virtual Task MoveFileAsync(FileCopyOrMoveDto input) + { + string fileSystemPath = GetFileSystemPath(input.Path); + fileSystemPath = Path.Combine(fileSystemPath, input.Name); + if (!File.Exists(fileSystemPath)) + { + throw new UserFriendlyException("指定目录不存在!"); + } + var moveToFilePath = GetFileSystemPath(input.ToPath); + moveToFilePath = Path.Combine(moveToFilePath, input.ToName ?? input.Name); + if (Directory.Exists(moveToFilePath)) + { + throw new UserFriendlyException("指定的路径中已经有同名的文件存在!"); + } + + File.Move(fileSystemPath, moveToFilePath); + + return Task.CompletedTask; + } + + public virtual Task MoveFolderAsync([Required, StringLength(255)] string path, FolderMoveDto input) + { + string fileSystemPath = GetFileSystemPath(path); + if (!Directory.Exists(fileSystemPath)) + { + throw new UserFriendlyException("指定目录不存在!"); + } + var moveToFilePath = GetFileSystemPath(input.MoveToPath); + if (Directory.Exists(moveToFilePath)) + { + throw new UserFriendlyException("指定的路径中已经有同名的目录存在!"); + } + + Directory.Move(fileSystemPath, moveToFilePath); + + return Task.CompletedTask; + } + + public virtual Task UpdateAsync([Required, StringLength(255)] string name, FileSystemUpdateDto input) + { + string fileSystemPath = GetFileSystemPath(name); + var renameFilePath = GetFileSystemPath(input.NewName); + if (File.Exists(fileSystemPath)) + { + if (File.Exists(renameFilePath)) + { + throw new UserFriendlyException("指定的文件名已经存在!"); + } + File.Move(fileSystemPath, renameFilePath); + + var fileInfo = new FileInfo(renameFilePath); + var fileSystem = new FileSystemDto + { + Type = FileSystemType.File, + Name = fileInfo.Name, + Size = fileInfo.Length, + CreationTime = fileInfo.CreationTime, + LastModificationTime = fileInfo.LastWriteTime + }; + if (fileInfo.Directory?.Parent != null && !fileInfo.Directory.Parent.Name.IsNullOrWhiteSpace()) + { + fileSystem.Parent = GetFileSystemRelativePath(fileInfo.Directory.Parent.FullName); + } + return Task.FromResult(fileSystem); + } + if (Directory.Exists(fileSystemPath)) + { + if (Directory.Exists(renameFilePath)) + { + throw new UserFriendlyException("指定的路径中已经有同名的目录存在!"); + } + + Directory.Move(fileSystemPath, renameFilePath); + + var directoryInfo = new DirectoryInfo(renameFilePath); + var fileSystem = new FileSystemDto + { + Type = FileSystemType.Folder, + Name = directoryInfo.Name, + CreationTime = directoryInfo.CreationTime, + LastModificationTime = directoryInfo.LastWriteTime + }; + if (directoryInfo.Parent != null && !directoryInfo.Parent.Name.IsNullOrWhiteSpace()) + { + fileSystem.Parent = GetFileSystemRelativePath(directoryInfo.Parent.FullName); + } + return Task.FromResult(fileSystem); + } + throw new UserFriendlyException("文件或目录不存在!"); + } + + protected virtual string GetFileSystemRelativePath(string path) + { + return path.Replace(Directory.GetCurrentDirectory(), ""); + } + + protected virtual string GetFileSystemPath(string path) + { + var fileSystemConfiguration = GetFileSystemBlobProviderConfiguration(); + var blobPath = GetFileSystemBashPath(); + + if (fileSystemConfiguration.AppendContainerNameToBasePath) + { + blobPath = Path.Combine(blobPath, path); + } + + return blobPath; + } + + protected virtual string GetFileSystemBashPath() + { + var fileSystemConfiguration = GetFileSystemBlobProviderConfiguration(); + var blobPath = fileSystemConfiguration.BasePath; + blobPath = Path.Combine(Directory.GetCurrentDirectory(), blobPath); + if (CurrentTenant.Id == null) + { + blobPath = Path.Combine(blobPath, "host"); + } + else + { + blobPath = Path.Combine(blobPath, "tenants", CurrentTenant.Id.Value.ToString("D")); + } + + return blobPath; + } + + protected virtual FileSystemBlobProviderConfiguration GetFileSystemBlobProviderConfiguration() + { + var blobConfiguration = BlobContainerConfigurationProvider + .Get(); + return blobConfiguration.GetFileSystemConfiguration(); + } + + protected void CopyDirectory(string sourcePath, string copyToPath) + { + var sourceDirectory = new DirectoryInfo(sourcePath); + var fileSystemInfos = sourceDirectory.GetFileSystemInfos(); + + foreach (var fileSystemInfo in fileSystemInfos) + { + var copyToFilePath = Path.Combine(copyToPath, fileSystemInfo.Name); + if (fileSystemInfo is DirectoryInfo) + { + if (!Directory.Exists(copyToFilePath)) + { + Directory.CreateDirectory(copyToFilePath); + } + CopyDirectory(fileSystemInfo.FullName, copyToFilePath); + } + else + { + File.Copy(fileSystemInfo.FullName, copyToFilePath, true); + } + } + + } + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN.Abp.FileManagement.Domain.Shared.csproj b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN.Abp.FileManagement.Domain.Shared.csproj new file mode 100644 index 000000000..b26f20fbb --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN.Abp.FileManagement.Domain.Shared.csproj @@ -0,0 +1,22 @@ + + + + netstandard2.0 + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/AbpFileManagementDomainSharedModule.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/AbpFileManagementDomainSharedModule.cs new file mode 100644 index 000000000..fe39e6a5e --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/AbpFileManagementDomainSharedModule.cs @@ -0,0 +1,30 @@ +using LINGYUN.Abp.FileManagement.Localization; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.Validation; +using Volo.Abp.Validation.Localization; +using Volo.Abp.VirtualFileSystem; + +namespace LINGYUN.Abp.FileManagement +{ + [DependsOn(typeof(AbpValidationModule))] + public class AbpFileManagementDomainSharedModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + + Configure(options => + { + options.Resources + .Add("en") + .AddBaseTypes( + typeof(AbpValidationResource) + ).AddVirtualJson("/LINGYUN/Abp/FileManagement/Localization/Resources"); + }); + } + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/Localization/AbpFileManagementResource.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/Localization/AbpFileManagementResource.cs new file mode 100644 index 000000000..4648b937d --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/Localization/AbpFileManagementResource.cs @@ -0,0 +1,9 @@ +using Volo.Abp.Localization; + +namespace LINGYUN.Abp.FileManagement.Localization +{ + [LocalizationResourceName("AbpFileManagement")] + public class AbpFileManagementResource + { + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/Localization/Resources/en.json b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/Localization/Resources/en.json new file mode 100644 index 000000000..5635784f2 --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/Localization/Resources/en.json @@ -0,0 +1,25 @@ +{ + "culture": "en", + "texts": { + "Permission:FileManagement": "File management", + "Permission:FileSystem": "File system", + "Permission:FileManager": "Files", + "Permission:CreateFolder": "Create directory", + "Permission:DeleteFolder": "Delete directory", + "Permission:UpdateFolder": "Edit directory", + "Permission:MoveFolder": "Change directory", + "Permission:CopyFolder": "Copy directory", + "Permission:AppendFile": "Add files", + "Permission:UpdateFile": "Change file", + "Permission:DeleteFile": "Delete file", + "Permission:CopyFile": "Copy file", + "Permission:MoveFile": "Move file", + "Permission:DownloadFile": "Download file", + "UploadFileSizeBeyondLimit": "Upload file size cannot exceed {0} MB!", + "NotAllowedFileExtensionName": "Not allowed file extension: {0}!", + "DisplayName:FileLimitLength": "File limit size", + "Description:FileLimitLength": "Limit size of uploaded file in MB", + "DisplayName:AllowFileExtensions": "File extension", + "Description:AllowFileExtensions": "List of allowed extensions to upload files, with multiple extensions separated by, don't need a notation" + } +} \ No newline at end of file diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/Localization/Resources/zh-Hans.json b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/Localization/Resources/zh-Hans.json new file mode 100644 index 000000000..e9b15e961 --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/Localization/Resources/zh-Hans.json @@ -0,0 +1,25 @@ +{ + "culture": "zh-Hans", + "texts": { + "Permission:FileManagement": "文件管理", + "Permission:FileSystem": "文件系统", + "Permission:FileManager": "文件", + "Permission:CreateFolder": "创建目录", + "Permission:DeleteFolder": "删除目录", + "Permission:UpdateFolder": "修改目录", + "Permission:MoveFolder": "变更目录", + "Permission:CopyFolder": "复制目录", + "Permission:AppendFile": "添加文件", + "Permission:UpdateFile": "变更文件", + "Permission:DeleteFile": "删除文件", + "Permission:CopyFile": "复制文件", + "Permission:MoveFile": "移动文件", + "Permission:DownloadFile": "下载文件", + "UploadFileSizeBeyondLimit": "上传文件大小不能超过 {0} MB!", + "NotAllowedFileExtensionName": "不被允许的文件扩展名: {0}!", + "DisplayName:FileLimitLength": "文件限制大小", + "Description:FileLimitLength": "上传文件的限制大小,单位(MB)", + "DisplayName:AllowFileExtensions": "文件扩展名", + "Description:AllowFileExtensions": "允许的上传文件扩展名列表,多个扩展名以,分隔,无需输入.符号" + } +} \ No newline at end of file diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/Settings/AbpFileManagementSettingNames.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/Settings/AbpFileManagementSettingNames.cs new file mode 100644 index 000000000..18d24cf18 --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/Settings/AbpFileManagementSettingNames.cs @@ -0,0 +1,18 @@ +namespace LINGYUN.Abp.FileManagement.Settings +{ + public class AbpFileManagementSettingNames + { + public const string GroupName = "Abp.FileManagement"; + /// + /// 文件限制长度 + /// + public const string FileLimitLength = GroupName + ".FileLimitLength"; + /// + /// 允许的文件扩展名类型 + /// + public const string AllowFileExtensions = GroupName + ".AllowFileExtensions"; + + public const int DefaultFileLimitLength = 100; + public const string DefaultAllowFileExtensions = "dll,zip,rar,txt,log,xml,config,json,jpeg,jpg,png,bmp,ico,xlsx,xltx,xls,xlt,docs,dots,doc,dot,pptx,potx,ppt,pot,chm"; + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain/LINGYUN.Abp.FileManagement.Domain.csproj b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain/LINGYUN.Abp.FileManagement.Domain.csproj new file mode 100644 index 000000000..fbc7b1b4c --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain/LINGYUN.Abp.FileManagement.Domain.csproj @@ -0,0 +1,16 @@ + + + + netstandard2.0 + + + + + + + + + + + + diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain/LINGYUN/Abp/FileManagement/AbpFileManagementDomainModule.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain/LINGYUN/Abp/FileManagement/AbpFileManagementDomainModule.cs new file mode 100644 index 000000000..f3781044f --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain/LINGYUN/Abp/FileManagement/AbpFileManagementDomainModule.cs @@ -0,0 +1,15 @@ +using Volo.Abp.Domain; +using Volo.Abp.Modularity; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.FileManagement +{ + [DependsOn( + typeof(AbpDddDomainModule), + typeof(AbpMultiTenancyModule), + typeof(AbpFileManagementDomainSharedModule) + )] + public class AbpFileManagementDomainModule : AbpModule + { + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain/LINGYUN/Abp/FileManagement/FileSystemContainer.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain/LINGYUN/Abp/FileManagement/FileSystemContainer.cs new file mode 100644 index 000000000..42c643e8f --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain/LINGYUN/Abp/FileManagement/FileSystemContainer.cs @@ -0,0 +1,9 @@ +using Volo.Abp.BlobStoring; + +namespace LINGYUN.Abp.FileManagement +{ + [BlobContainerName("abp-file-management")] + public class FileSystemContainer + { + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain/LINGYUN/Abp/FileManagement/Settings/AbpFileManagementSettingDefinitionProvider.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain/LINGYUN/Abp/FileManagement/Settings/AbpFileManagementSettingDefinitionProvider.cs new file mode 100644 index 000000000..b93566816 --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain/LINGYUN/Abp/FileManagement/Settings/AbpFileManagementSettingDefinitionProvider.cs @@ -0,0 +1,44 @@ +using LINGYUN.Abp.FileManagement.Localization; +using Volo.Abp.Localization; +using Volo.Abp.Settings; + +namespace LINGYUN.Abp.FileManagement.Settings +{ + public class AbpFileManagementSettingDefinitionProvider : SettingDefinitionProvider + { + public override void Define(ISettingDefinitionContext context) + { + context.Add(CreateFileSystemSettings()); + } + + protected SettingDefinition[] CreateFileSystemSettings() + { + return new SettingDefinition[] + { + new SettingDefinition( + name: AbpFileManagementSettingNames.FileLimitLength, + defaultValue: AbpFileManagementSettingNames.DefaultFileLimitLength.ToString(), + displayName: L("DisplayName:FileLimitLength"), + description: L("Description:FileLimitLength"), + isVisibleToClients: true) + .WithProviders( + GlobalSettingValueProvider.ProviderName, + TenantSettingValueProvider.ProviderName), + new SettingDefinition( + name: AbpFileManagementSettingNames.AllowFileExtensions, + defaultValue: AbpFileManagementSettingNames.DefaultAllowFileExtensions, + displayName: L("DisplayName:AllowFileExtensions"), + description: L("Description:AllowFileExtensions"), + isVisibleToClients: true) + .WithProviders( + GlobalSettingValueProvider.ProviderName, + TenantSettingValueProvider.ProviderName), + }; + } + + protected LocalizableString L(string name) + { + return LocalizableString.Create(name); + } + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN.Abp.FileManagement.HttpApi.csproj b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN.Abp.FileManagement.HttpApi.csproj new file mode 100644 index 000000000..c2849e212 --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN.Abp.FileManagement.HttpApi.csproj @@ -0,0 +1,16 @@ + + + + netcoreapp3.1 + + + + + + + + + + + + diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN/Abp/FileManagement/AbpFileManagementHttpApiModule.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN/Abp/FileManagement/AbpFileManagementHttpApiModule.cs new file mode 100644 index 000000000..f8d61cf03 --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN/Abp/FileManagement/AbpFileManagementHttpApiModule.cs @@ -0,0 +1,21 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.FileManagement +{ + [DependsOn( + typeof(AbpFileManagementApplicationContractsModule), + typeof(AbpAspNetCoreMvcModule) + )] + public class AbpFileManagementHttpApiModule : AbpModule + { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(mvcBuilder => + { + mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpFileManagementHttpApiModule).Assembly); + }); + } + } +} diff --git a/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN/Abp/FileManagement/FileSystemController.cs b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN/Abp/FileManagement/FileSystemController.cs new file mode 100644 index 000000000..52f242ca3 --- /dev/null +++ b/aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN/Abp/FileManagement/FileSystemController.cs @@ -0,0 +1,240 @@ +using LINGYUN.Abp.FileManagement.Settings; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.StaticFiles; +using System; +using System.ComponentModel.DataAnnotations; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.Application.Dtos; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.IO; +using Volo.Abp.Settings; + +namespace LINGYUN.Abp.FileManagement +{ + [Controller] + [RemoteService(Name = "AbpFileManagement")] + [Area("file-management")] + [Route("api/file-management/file-system")] + public class FileSystemController : AbpController + { + protected ISettingProvider SettingProvider { get; } + protected IFileSystemAppService FileSystemAppService { get; } + + public FileSystemController( + ISettingProvider settingProvider, + IFileSystemAppService fileSystemAppService) + { + SettingProvider = settingProvider; + FileSystemAppService = fileSystemAppService; + } + + [HttpPut] + [Route("files/copy")] + public virtual async Task CopyFileAsync(FileCopyOrMoveDto input) + { + await FileSystemAppService.CopyFileAsync(input); + } + + [HttpPut] + [Route("folders/copy")] + public virtual async Task CopyFolderAsync([Required, StringLength(255)] string path, FolderCopyDto input) + { + await FileSystemAppService.CopyFolderAsync(path, input); + } + + [HttpPost] + [Route("files/upload")] + public virtual async Task CreateFileAsync(FileCreateDto input) + { + // 检查文件大小 + var fileSizeLimited = await SettingProvider + .GetAsync( + AbpFileManagementSettingNames.FileLimitLength, + AbpFileManagementSettingNames.DefaultFileLimitLength); + if (fileSizeLimited * 1024 * 1024 < input.TotalByte) + { + throw new UserFriendlyException(L["UploadFileSizeBeyondLimit", fileSizeLimited]); + } + // 采用分块模式上传文件 + + // 保存分块到临时目录 + var fileName = input.Name; + // 文件扩展名 + var fileExtensionName = FileHelper.GetExtension(fileName); + var fileAllowExtension = await SettingProvider + .GetOrNullAsync(AbpFileManagementSettingNames.AllowFileExtensions); + if (fileAllowExtension.IsNullOrWhiteSpace()) + { + fileAllowExtension = AbpFileManagementSettingNames.DefaultAllowFileExtensions; + } + // 检查文件扩展名 + if (!fileAllowExtension.Split(',') + .Any(fe => fe.Equals(fileExtensionName, StringComparison.CurrentCultureIgnoreCase))) + { + throw new UserFriendlyException(L["NotAllowedFileExtensionName", fileExtensionName]); + } + // 当前计算机临时目录 + var tempFilePath = Environment.GetFolderPath(Environment.SpecialFolder.Templates); + // 以上传的文件名创建一个临时目录 + tempFilePath = Path.Combine(tempFilePath, "lingyun-abp-file-management", Path.GetFileNameWithoutExtension(fileName)); + // 以上传的分片索引创建临时文件 + var tempSavedFile = Path.Combine(tempFilePath, $"{input.CurrentByte}.{fileExtensionName}"); + if (!Directory.Exists(tempFilePath)) + { + // 临时目录不存在则创建 + Directory.CreateDirectory(tempFilePath); + } + try + { + if (HttpContext.RequestAborted.IsCancellationRequested) + { + // 如果取消请求,删除临时目录 + Directory.Delete(tempFilePath, true); + return; + } + // 保存临时文件 + using (var fs = new FileStream(tempSavedFile, FileMode.Create, FileAccess.Write)) + { + // 写入当前分片文件 + await Request.Body.CopyToAsync(fs); + } + + if (input.CurrentByte == input.TotalByte) + { + // 合并文件 + var mergeSavedFile = Path.Combine(tempFilePath, $"{fileName}"); + // 获取并排序所有分片文件 + var mergeFiles = Directory.GetFiles(tempFilePath).OrderBy(f => f.Length).ThenBy(f => f); + // 创建临时合并文件 + using (var mergeSavedFileStream = new FileStream(mergeSavedFile, FileMode.Create)) + { + foreach (var mergeFile in mergeFiles) + { + // 读取当前文件字节 + var mergeFileBytes = await FileHelper.ReadAllBytesAsync(mergeFile); + // 写入到合并文件流 + await mergeSavedFileStream.WriteAsync(mergeFileBytes, 0, mergeFileBytes.Length); + // 删除已参与合并的临时文件分片 + FileHelper.DeleteIfExists(mergeFile); + } + // 读取文件数据 + var fileData = await mergeSavedFileStream.GetAllBytesAsync(); + input.Data = fileData; + } + await FileSystemAppService.CreateFileAsync(input); + // 文件保存之后删除临时文件目录 + Directory.Delete(tempFilePath, true); + } + } + catch + { + // 发生异常删除临时文件目录 + Directory.Delete(tempFilePath, true); + throw; + } + } + + [HttpPost] + [Route("folders/add")] + public virtual async Task CreateFolderAsync(FolderCreateDto input) + { + await FileSystemAppService.CreateFolderAsync(input); + } + + [HttpDelete] + [Route("files/delete")] + public virtual async Task DeleteFileAsync(FileDeleteDto input) + { + await FileSystemAppService.DeleteFileAsync(input); + } + + [HttpDelete] + [Route("folders/delete")] + public virtual async Task DeleteFolderAsync([Required, StringLength(255)] string path) + { + await FileSystemAppService.DeleteFolderAsync(path); + } + + [HttpGet] + [Route("files/download")] + public virtual async Task DownloadFileAsync(FileSystemGetDto input) + { + var fileStream = await FileSystemAppService.DownloadFileAsync(input); + + // 得到文件扩展名 + var fileExt = Path.GetExtension(input.Name); + var provider = new FileExtensionContentTypeProvider(); + // Http响应标头的文件类型 + string memi = provider.Mappings[fileExt]; + using (Response.Body) + { + // Http响应标头的文件类型 + Response.ContentType = memi; + // 文件大小 + byte[] contentBytes = await fileStream.GetAllBytesAsync(); + long contentLength = contentBytes.Length; + // 指定响应内容大小 + Response.ContentLength = contentLength; + // 单个分块大小 2MB + int bufferSize = 2 * 1024 * 1024; + // 分块总数 + int contentByteCount = Math.DivRem(contentBytes.Length, bufferSize, out int modResult); + for (int index = 0; index < contentByteCount; index++) + { + // 当前分页传输字节 + byte[] currentTransferBytes = new byte[bufferSize]; + if (index == contentByteCount - 1) + { + // 最后一个分块和余数大小一起传输 + if (modResult > 0) + { + currentTransferBytes = new byte[bufferSize + modResult]; + } + } + // 复制文件流中的当前分块区段 + Array.Copy(contentBytes, index * bufferSize, currentTransferBytes, 0, currentTransferBytes.Length); + // 写入响应流 + await Response.Body.WriteAsync(currentTransferBytes, 0, currentTransferBytes.Length); + // 清空缓冲区 + await Response.Body.FlushAsync(); + } + } + } + + [HttpGet] + [Route("profile")] + public virtual async Task GetAsync(FileSystemGetDto input) + { + return await FileSystemAppService.GetAsync(input); + } + + [HttpGet] + public virtual async Task> GetListAsync(GetFileSystemListDto input) + { + return await FileSystemAppService.GetListAsync(input); + } + + [HttpPut] + [Route("files/move")] + public virtual async Task MoveFileAsync(FileCopyOrMoveDto input) + { + await FileSystemAppService.MoveFileAsync(input); + } + + [HttpPut] + [Route("folders/move")] + public virtual async Task MoveFolderAsync([Required, StringLength(255)] string path, FolderMoveDto input) + { + await FileSystemAppService.MoveFolderAsync(path, input); + } + + [HttpPut] + public virtual async Task UpdateAsync([Required, StringLength(255)] string name, FileSystemUpdateDto input) + { + return await FileSystemAppService.UpdateAsync(name, input); + } + } +} diff --git a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/AppPlatformDomainModule.cs b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/AppPlatformDomainModule.cs index c68379d0a..b4a3786b1 100644 --- a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/AppPlatformDomainModule.cs +++ b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/AppPlatformDomainModule.cs @@ -41,6 +41,8 @@ namespace LINGYUN.Platform options.EtoMappings.Add(typeof(AppPlatformDomainModule)); options.EtoMappings.Add(typeof(AppPlatformDomainModule)); + + options.AutoEventSelectors.Add(); }); } public override void PostConfigureServices(ServiceConfigurationContext context) diff --git a/aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application/LINGYUN/Abp/TenantManagement/AbpTenantManagementApplicationModule.cs b/aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application/LINGYUN/Abp/TenantManagement/AbpTenantManagementApplicationModule.cs index 4dfbb6b9b..2a247a936 100644 --- a/aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application/LINGYUN/Abp/TenantManagement/AbpTenantManagementApplicationModule.cs +++ b/aspnet-core/modules/tenants/LINGYUN.Abp.TenantManagement.Application/LINGYUN/Abp/TenantManagement/AbpTenantManagementApplicationModule.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.AutoMapper; +using Volo.Abp.Domain.Entities.Events.Distributed; using Volo.Abp.Modularity; using Volo.Abp.TenantManagement; @@ -17,6 +18,11 @@ namespace LINGYUN.Abp.TenantManagement { options.AddProfile(validate: true); }); + + Configure(options => + { + options.AutoEventSelectors.Add(); + }); } } } diff --git a/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/AppPlatformHttpApiHostModule.cs b/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/AppPlatformHttpApiHostModule.cs index bccd24c78..5fb3e6d81 100644 --- a/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/AppPlatformHttpApiHostModule.cs +++ b/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/AppPlatformHttpApiHostModule.cs @@ -3,6 +3,7 @@ using IdentityModel; using LINGYUN.Abp.EventBus.CAP; using LINGYUN.Abp.ExceptionHandling; using LINGYUN.Abp.ExceptionHandling.Emailing; +using LINGYUN.Abp.FileManagement; using LINGYUN.Abp.Notifications; using LINGYUN.Platform.EntityFrameworkCore; using LINGYUN.Platform.HttpApi; @@ -40,6 +41,8 @@ using Volo.Abp.VirtualFileSystem; namespace LINGYUN.Platform { [DependsOn( + typeof(AbpFileManagementApplicationModule), + typeof(AbpFileManagementHttpApiModule), typeof(AppPlatformApplicationModule), typeof(AppPlatformHttpApiModule), typeof(AppPlatformEntityFrameworkCoreModule), diff --git a/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj b/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj index 9b89562f0..c24fefacc 100644 --- a/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj +++ b/aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj @@ -42,6 +42,8 @@ + + diff --git a/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/TestObjects/TestContainer1.cs b/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/TestObjects/TestContainer1.cs index 47562c6a3..2df7073c4 100644 --- a/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/TestObjects/TestContainer1.cs +++ b/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/TestObjects/TestContainer1.cs @@ -1,5 +1,8 @@ -namespace LINGYUN.Abp.BlobStoring.TestObjects +using Volo.Abp.BlobStoring; + +namespace LINGYUN.Abp.BlobStoring.TestObjects { + [BlobContainerName("abp-blob-storing-test-container")] public class TestContainer1 { }