diff --git a/aspnet-core/LINGYUN.MicroService.All.sln b/aspnet-core/LINGYUN.MicroService.All.sln index 473f1f944..593746f77 100644 --- a/aspnet-core/LINGYUN.MicroService.All.sln +++ b/aspnet-core/LINGYUN.MicroService.All.sln @@ -353,6 +353,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OpenApi.Authori EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Wrapper", "modules\common\LINGYUN.Abp.Wrapper\LINGYUN.Abp.Wrapper.csproj", "{65311EC9-7A86-4E73-A587-F06A99474EDD}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.BlobStoring.OssManagement", "modules\oss-management\LINGYUN.Abp.BlobStoring.OssManagement\LINGYUN.Abp.BlobStoring.OssManagement.csproj", "{CD9081C6-7CA0-4A93-9318-33E54F3ED275}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OssManagement.HttpApi.Client", "modules\oss-management\LINGYUN.Abp.OssManagement.HttpApi.Client\LINGYUN.Abp.OssManagement.HttpApi.Client.csproj", "{D262405E-1C72-4F14-A799-40471BAD48DC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -915,6 +919,14 @@ Global {65311EC9-7A86-4E73-A587-F06A99474EDD}.Debug|Any CPU.Build.0 = Debug|Any CPU {65311EC9-7A86-4E73-A587-F06A99474EDD}.Release|Any CPU.ActiveCfg = Release|Any CPU {65311EC9-7A86-4E73-A587-F06A99474EDD}.Release|Any CPU.Build.0 = Release|Any CPU + {CD9081C6-7CA0-4A93-9318-33E54F3ED275}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CD9081C6-7CA0-4A93-9318-33E54F3ED275}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CD9081C6-7CA0-4A93-9318-33E54F3ED275}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CD9081C6-7CA0-4A93-9318-33E54F3ED275}.Release|Any CPU.Build.0 = Release|Any CPU + {D262405E-1C72-4F14-A799-40471BAD48DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D262405E-1C72-4F14-A799-40471BAD48DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D262405E-1C72-4F14-A799-40471BAD48DC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D262405E-1C72-4F14-A799-40471BAD48DC}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1089,6 +1101,8 @@ Global {4059F87E-9762-46C1-AEB1-B1128EA533AE} = {3C7A8246-DE82-4330-8697-24EF1B1C515D} {433AD1FB-2DE8-479F-B89E-A17217591538} = {3C7A8246-DE82-4330-8697-24EF1B1C515D} {65311EC9-7A86-4E73-A587-F06A99474EDD} = {8AC72641-30D3-4ACF-89FA-808FADC55C2E} + {CD9081C6-7CA0-4A93-9318-33E54F3ED275} = {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6} + {D262405E-1C72-4F14-A799-40471BAD48DC} = {B05CB08F-C088-4D6D-97EE-A94A5D1AE4A6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C95FDF91-16F2-4A8B-A4BE-0E62D1B66718} diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/FodyWeavers.xml b/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/FodyWeavers.xml new file mode 100644 index 000000000..ac6b5b292 --- /dev/null +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/FodyWeavers.xsd b/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/FodyWeavers.xsd new file mode 100644 index 000000000..11da52550 --- /dev/null +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN.Abp.BlobStoring.OssManagement.csproj b/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN.Abp.BlobStoring.OssManagement.csproj new file mode 100644 index 000000000..05a77d6d7 --- /dev/null +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN.Abp.BlobStoring.OssManagement.csproj @@ -0,0 +1,19 @@ + + + + + + + netstandard2.0 + + + + + + + + + + + + diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/AbpBlobStoringOssManagementModule.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/AbpBlobStoringOssManagementModule.cs new file mode 100644 index 000000000..509b4f779 --- /dev/null +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/AbpBlobStoringOssManagementModule.cs @@ -0,0 +1,12 @@ +using LINGYUN.Abp.OssManagement; +using Volo.Abp.BlobStoring; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.BlobStoring.OssManagement +{ + [DependsOn(typeof(AbpBlobStoringModule))] + [DependsOn(typeof(AbpOssManagementHttpApiClientModule))] + public class AbpBlobStoringOssManagementModule : AbpModule + { + } +} diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobContainerConfigurationExtensions.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobContainerConfigurationExtensions.cs new file mode 100644 index 000000000..d485da99d --- /dev/null +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobContainerConfigurationExtensions.cs @@ -0,0 +1,25 @@ +using System; +using Volo.Abp.BlobStoring; + +namespace LINGYUN.Abp.BlobStoring.OssManagement; + +public static class OssManagementBlobContainerConfigurationExtensions +{ + public static OssManagementBlobProviderConfiguration GetOssManagementConfiguration( + this BlobContainerConfiguration containerConfiguration) + { + return new OssManagementBlobProviderConfiguration(containerConfiguration); + } + + public static BlobContainerConfiguration UseOssManagement( + this BlobContainerConfiguration containerConfiguration, + Action fileSystemConfigureAction) + { + containerConfiguration.ProviderType = typeof(OssManagementBlobProvider); + containerConfiguration.NamingNormalizers.TryAdd(); + + fileSystemConfigureAction(new OssManagementBlobProviderConfiguration(containerConfiguration)); + + return containerConfiguration; + } +} diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobNamingNormalizer.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobNamingNormalizer.cs new file mode 100644 index 000000000..5a6ffbba9 --- /dev/null +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobNamingNormalizer.cs @@ -0,0 +1,23 @@ +using System; +using System.Text; +using System.Web; +using Volo.Abp.BlobStoring; +using Volo.Abp.DependencyInjection; + +namespace LINGYUN.Abp.BlobStoring.OssManagement +{ + public class OssManagementBlobNamingNormalizer : IBlobNamingNormalizer, ITransientDependency + { + public string NormalizeBlobName(string blobName) + { + // 路径需要URL编码 + return HttpUtility.UrlEncode(blobName, Encoding.UTF8); + } + + public string NormalizeContainerName(string containerName) + { + // 取消反斜杠开头 + return containerName.EnsureStartsWith('/'); + } + } +} diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobProvider.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobProvider.cs new file mode 100644 index 000000000..b1364ff3c --- /dev/null +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobProvider.cs @@ -0,0 +1,92 @@ +using LINGYUN.Abp.OssManagement; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using System; +using System.IO; +using System.Threading.Tasks; +using Volo.Abp.BlobStoring; +using Volo.Abp.Content; +using Volo.Abp.DependencyInjection; + +namespace LINGYUN.Abp.BlobStoring.OssManagement +{ + public class OssManagementBlobProvider : BlobProviderBase, ITransientDependency + { + public ILogger Logger { protected get; set; } + + private readonly IOssObjectAppService _ossObjectAppService; + public OssManagementBlobProvider( + IOssObjectAppService ossObjectAppService) + { + _ossObjectAppService = ossObjectAppService; + + Logger = NullLogger.Instance; + } + + public override async Task DeleteAsync(BlobProviderDeleteArgs args) + { + var configuration = args.Configuration.GetOssManagementConfiguration(); + await _ossObjectAppService.DeleteAsync(new GetOssObjectInput + { + Bucket = configuration.Bucket, + Object = args.BlobName + }); + return true; + } + + public override async Task ExistsAsync(BlobProviderExistsArgs args) + { + try + { + var configuration = args.Configuration.GetOssManagementConfiguration(); + var oss = await _ossObjectAppService.GetAsync(new GetOssObjectInput + { + Bucket = configuration.Bucket, + Object = args.BlobName + }); + return oss != null; + } + catch (Exception ex) + { + Logger.LogWarning("An error occurred while getting the OSS object, always returning that the object does not exist"); + Logger.LogWarning(ex.Message); + + return false; + } + } + + public override async Task GetOrNullAsync(BlobProviderGetArgs args) + { + try + { + var configuration = args.Configuration.GetOssManagementConfiguration(); + var content = await _ossObjectAppService.GetContentAsync(new GetOssObjectInput + { + Bucket = configuration.Bucket, + Object = args.BlobName + }); + + return content?.GetStream(); + } + catch(Exception ex) + { + Logger.LogWarning("An error occurred while getting the OSS object and an empty data stream will be returned"); + Logger.LogWarning(ex.Message); + + return Stream.Null; + } + } + + public override async Task SaveAsync(BlobProviderSaveArgs args) + { + var configuration = args.Configuration.GetOssManagementConfiguration(); + await _ossObjectAppService.CreateAsync(new CreateOssObjectInput + { + Bucket = configuration.Bucket, + Overwrite = true, + FileName = args.BlobName, + File = new RemoteStreamContent(args.BlobStream) + }); + } + } +} diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobProviderConfiguration.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobProviderConfiguration.cs new file mode 100644 index 000000000..cb8c5502b --- /dev/null +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobProviderConfiguration.cs @@ -0,0 +1,21 @@ +using Volo.Abp; +using Volo.Abp.BlobStoring; + +namespace LINGYUN.Abp.BlobStoring.OssManagement +{ + public class OssManagementBlobProviderConfiguration + { + public string Bucket + { + get => _containerConfiguration.GetConfiguration(OssManagementBlobProviderConfigurationNames.Bucket); + set => _containerConfiguration.SetConfiguration(OssManagementBlobProviderConfigurationNames.Bucket, Check.NotNullOrWhiteSpace(value, nameof(value))); + } + + private readonly BlobContainerConfiguration _containerConfiguration; + + public OssManagementBlobProviderConfiguration(BlobContainerConfiguration containerConfiguration) + { + _containerConfiguration = containerConfiguration; + } + } +} diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobProviderConfigurationNames.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobProviderConfigurationNames.cs new file mode 100644 index 000000000..489d4c359 --- /dev/null +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.BlobStoring.OssManagement/LINGYUN/Abp/BlobStoring/OssManagement/OssManagementBlobProviderConfigurationNames.cs @@ -0,0 +1,7 @@ +namespace LINGYUN.Abp.BlobStoring.OssManagement +{ + public class OssManagementBlobProviderConfigurationNames + { + public const string Bucket = "OssManagement:Bucket"; + } +} diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/IOssObjectAppService.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/IOssObjectAppService.cs index bd4377e4f..d90ece811 100644 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/IOssObjectAppService.cs +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/IOssObjectAppService.cs @@ -1,6 +1,7 @@ using System.Threading.Tasks; using Volo.Abp.Application.Services; - +using Volo.Abp.Content; + namespace LINGYUN.Abp.OssManagement { public interface IOssObjectAppService : IApplicationService @@ -9,6 +10,8 @@ namespace LINGYUN.Abp.OssManagement Task GetAsync(GetOssObjectInput input); + Task GetContentAsync(GetOssObjectInput input); + Task DeleteAsync(GetOssObjectInput input); Task BulkDeleteAsync(BulkDeleteOssObjectInput input); diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/OssObjectAppService.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/OssObjectAppService.cs index ce395333f..c59f45854 100644 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/OssObjectAppService.cs +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/OssObjectAppService.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Authorization; using System.IO; using System.Threading.Tasks; using System.Web; +using Volo.Abp.Content; namespace LINGYUN.Abp.OssManagement { @@ -69,6 +70,15 @@ namespace LINGYUN.Abp.OssManagement return ObjectMapper.Map(ossObject); } + public virtual async Task GetContentAsync(GetOssObjectInput input) + { + var oss = CreateOssContainer(); + + var ossObject = await oss.GetObjectAsync(input.Bucket, input.Object, input.Path, input.MD5); + + return new RemoteStreamContent(ossObject.Content, ossObject.Name); + } + protected virtual IOssContainer CreateOssContainer() { return OssContainerFactory.Create(); diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain/LINGYUN/Abp/OssManagement/AbpOssManagementOptions.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain/LINGYUN/Abp/OssManagement/AbpOssManagementOptions.cs index 38cdefd93..c800e316c 100644 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain/LINGYUN/Abp/OssManagement/AbpOssManagementOptions.cs +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain/LINGYUN/Abp/OssManagement/AbpOssManagementOptions.cs @@ -16,9 +16,16 @@ namespace LINGYUN.Abp.OssManagement { StaticBuckets = new List { + // 公共目录 "public", + // 用户私有目录 "users", + // 系统目录 "system", + // 工作流 + "workflow", + // 图标 + "icons" }; } diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/FodyWeavers.xsd b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/FodyWeavers.xsd new file mode 100644 index 000000000..11da52550 --- /dev/null +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/LINGYUN.Abp.OssManagement.HttpApi.Client.csproj b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/LINGYUN.Abp.OssManagement.HttpApi.Client.csproj index a646795a9..fb415f1bb 100644 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/LINGYUN.Abp.OssManagement.HttpApi.Client.csproj +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/LINGYUN.Abp.OssManagement.HttpApi.Client.csproj @@ -1,5 +1,6 @@ + @@ -8,7 +9,7 @@ - + diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/LINGYUN/Abp/OssManagement/LINGYUNApiDescriptionFinder.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/LINGYUN/Abp/OssManagement/LINGYUNApiDescriptionFinder.cs deleted file mode 100644 index 2fe15b2c0..000000000 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi.Client/LINGYUN/Abp/OssManagement/LINGYUNApiDescriptionFinder.cs +++ /dev/null @@ -1,162 +0,0 @@ -using Microsoft.Extensions.Options; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Reflection; -using System.Text; -using System.Text.Json; -using System.Threading.Tasks; -using Volo.Abp; -using Volo.Abp.DependencyInjection; -using Volo.Abp.Http.Client.DynamicProxying; -using Volo.Abp.Http.Modeling; -using Volo.Abp.MultiTenancy; -using Volo.Abp.Threading; -using Volo.Abp.Tracing; - -namespace LINGYUN.Abp.OssManagement -{ - public class LINGYUNApiDescriptionFinder : IApiDescriptionFinder, ITransientDependency - { - public ICancellationTokenProvider CancellationTokenProvider { get; set; } - protected IApiDescriptionCache Cache { get; } - protected AbpCorrelationIdOptions AbpCorrelationIdOptions { get; } - protected ICorrelationIdProvider CorrelationIdProvider { get; } - protected ICurrentTenant CurrentTenant { get; } - - public LINGYUNApiDescriptionFinder( - IApiDescriptionCache cache, - IOptions abpCorrelationIdOptions, - ICorrelationIdProvider correlationIdProvider, - ICurrentTenant currentTenant) - { - Cache = cache; - AbpCorrelationIdOptions = abpCorrelationIdOptions.Value; - CorrelationIdProvider = correlationIdProvider; - CurrentTenant = currentTenant; - CancellationTokenProvider = NullCancellationTokenProvider.Instance; - } - - public async Task FindActionAsync(HttpClient client, string baseUrl, Type serviceType, MethodInfo method) - { - var apiDescription = await GetApiDescriptionAsync(client, baseUrl); - - //TODO: Cache finding? - - var methodParameters = method.GetParameters().ToArray(); - - foreach (var module in apiDescription.Modules.Values) - { - foreach (var controller in module.Controllers.Values) - { - if (!controller.Implements(serviceType)) - { - continue; - } - - foreach (var action in controller.Actions.Values) - { - if (action.Name == method.Name && action.ParametersOnMethod.Count == methodParameters.Length) - { - var found = true; - - for (int i = 0; i < methodParameters.Length; i++) - { - if (!TypeMatches(action.ParametersOnMethod[i], methodParameters[i])) - { - found = false; - break; - } - } - - if (found) - { - return action; - } - } - } - } - } - - throw new AbpException($"Could not found remote action for method: {method} on the URL: {baseUrl}"); - } - - public virtual async Task GetApiDescriptionAsync(HttpClient client, string baseUrl) - { - return await Cache.GetAsync(baseUrl, () => GetApiDescriptionFromServerAsync(client, baseUrl)); - } - - protected virtual async Task GetApiDescriptionFromServerAsync( - HttpClient client, - string baseUrl) - { - var requestMessage = new HttpRequestMessage( - HttpMethod.Get, - baseUrl.EnsureEndsWith('/') + "api/abp/api-definition" - ); - - AddHeaders(requestMessage); - - var response = await client.SendAsync( - requestMessage, - CancellationTokenProvider.Token - ); - - if (!response.IsSuccessStatusCode) - { - throw new AbpException("Remote service returns error! StatusCode = " + response.StatusCode); - } - - var content = await response.Content.ReadAsStringAsync(); - - var result = JsonSerializer.Deserialize(content, new JsonSerializerOptions - { - PropertyNamingPolicy = JsonNamingPolicy.CamelCase - }); - - return (ApplicationApiDescriptionModel)result; - } - - protected virtual void AddHeaders(HttpRequestMessage requestMessage) - { - //CorrelationId - requestMessage.Headers.Add(AbpCorrelationIdOptions.HttpHeaderName, CorrelationIdProvider.Get()); - - //TenantId - if (CurrentTenant.Id.HasValue) - { - //TODO: Use AbpAspNetCoreMultiTenancyOptions to get the key - requestMessage.Headers.Add(TenantResolverConsts.DefaultTenantKey, CurrentTenant.Id.Value.ToString()); - } - - //Culture - //TODO: Is that the way we want? Couldn't send the culture (not ui culture) - var currentCulture = CultureInfo.CurrentUICulture.Name ?? CultureInfo.CurrentCulture.Name; - if (!currentCulture.IsNullOrEmpty()) - { - requestMessage.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(currentCulture)); - } - - //X-Requested-With - requestMessage.Headers.Add("X-Requested-With", "XMLHttpRequest"); - } - - protected virtual bool TypeMatches(MethodParameterApiDescriptionModel actionParameter, ParameterInfo methodParameter) - { - return NormalizeTypeName(actionParameter.TypeAsString) == - NormalizeTypeName(methodParameter.ParameterType.GetFullNameWithAssemblyName()); - } - - protected virtual string NormalizeTypeName(string typeName) - { - const string placeholder = "%COREFX%"; - const string netCoreLib = "System.Private.CoreLib"; - const string netFxLib = "mscorlib"; - - return typeName.Replace(netCoreLib, placeholder).Replace(netFxLib, placeholder); - } - } -} diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/OssObjectController.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/OssObjectController.cs index 0dbc09701..08942d48b 100644 --- a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/OssObjectController.cs +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/OssObjectController.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Volo.Abp; using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.Auditing; +using Volo.Abp.Content; namespace LINGYUN.Abp.OssManagement { @@ -25,7 +26,7 @@ namespace LINGYUN.Abp.OssManagement } [HttpPost] - public virtual async Task CreateAsync([FromForm] CreateOssObjectInput input) + public virtual async Task CreateAsync(CreateOssObjectInput input) { return await OssObjectAppService.CreateAsync(input); } @@ -57,5 +58,12 @@ namespace LINGYUN.Abp.OssManagement { return await OssObjectAppService.GetAsync(input); } + + [HttpGet] + [Route("download")] + public virtual async Task GetContentAsync(GetOssObjectInput input) + { + return await OssObjectAppService.GetContentAsync(input); + } } } diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN.Abp.WorkflowCore.Components.csproj b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN.Abp.WorkflowCore.Components.csproj index 41f84616c..c0ed1ec7a 100644 --- a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN.Abp.WorkflowCore.Components.csproj +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN.Abp.WorkflowCore.Components.csproj @@ -9,6 +9,7 @@ + diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/AbpWorkflowCoreComponentsModule.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/AbpWorkflowCoreComponentsModule.cs index cac71425a..d6f32653d 100644 --- a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/AbpWorkflowCoreComponentsModule.cs +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/AbpWorkflowCoreComponentsModule.cs @@ -1,4 +1,5 @@ -using Volo.Abp.Emailing; +using Volo.Abp.BlobStoring; +using Volo.Abp.Emailing; using Volo.Abp.Modularity; using Volo.Abp.Sms; @@ -7,6 +8,7 @@ namespace LINGYUN.Abp.WorkflowCore.Components [DependsOn( typeof(AbpSmsModule), typeof(AbpEmailingModule), + typeof(AbpBlobStoringModule), typeof(AbpWorkflowCoreModule))] public class AbpWorkflowCoreComponentsModule : AbpModule { diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/Primitives/SendEmail.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/Primitives/SendEmail.cs index 07e69b36a..08d443e78 100644 --- a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/Primitives/SendEmail.cs +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/Primitives/SendEmail.cs @@ -2,8 +2,12 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using System; +using System.Collections.Generic; using System.Globalization; +using System.IO; +using System.Net.Mail; using System.Threading.Tasks; +using Volo.Abp.BlobStoring; using Volo.Abp.Emailing; using Volo.Abp.Emailing.Templates; using Volo.Abp.TextTemplating; @@ -18,12 +22,15 @@ namespace LINGYUN.Abp.WorkflowCore.Components.Primitives private readonly IEmailSender _emailSender; private readonly ITemplateRenderer _templateRenderer; + private readonly IBlobContainer _blobContainer; public SendEmail( IEmailSender emailSender, - ITemplateRenderer templateRenderer) + ITemplateRenderer templateRenderer, + IBlobContainer blobContainer) { _emailSender = emailSender; + _blobContainer = blobContainer; _templateRenderer = templateRenderer; Logger = NullLogger.Instance; @@ -41,6 +48,9 @@ namespace LINGYUN.Abp.WorkflowCore.Components.Primitives [CanBeNull] public string Template { get; set; } + [CanBeNull] + public string Attachments { get; set; } + public override async Task RunAsync(IStepExecutionContext context) { Logger.LogInformation("Working on sending email step."); @@ -50,7 +60,28 @@ namespace LINGYUN.Abp.WorkflowCore.Components.Primitives Data, CultureInfo.CurrentCulture.Name); - await _emailSender.SendAsync(Receivers, Title, templateContent); + var mailMessage = new MailMessage + { + To = { Receivers }, + Subject = Title, + Body = templateContent, + IsBodyHtml = true + }; + + if (!Attachments.IsNullOrWhiteSpace()) + { + var attachments = Attachments.Split(';'); + foreach (var attachment in attachments) + { + var stream = await _blobContainer.GetOrNullAsync(attachment); + if (stream != null) + { + mailMessage.Attachments.Add(new Attachment(stream, Path.GetFileName(attachment))); + } + } + } + + await _emailSender.SendAsync(mailMessage); Logger.LogInformation("Email sent, forward to next step."); diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/WorkflowContainer.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/WorkflowContainer.cs new file mode 100644 index 000000000..b3e114482 --- /dev/null +++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Components/LINGYUN/Abp/WorkflowCore/Components/WorkflowContainer.cs @@ -0,0 +1,10 @@ +using Volo.Abp.BlobStoring; + +namespace LINGYUN.Abp.WorkflowCore.Components +{ + [BlobContainerName(Name)] + public class WorkflowContainer + { + public const string Name = "workflow"; + } +} diff --git a/aspnet-core/services/.gitignore b/aspnet-core/services/.gitignore index ee6673ebd..fe0a31716 100644 --- a/aspnet-core/services/.gitignore +++ b/aspnet-core/services/.gitignore @@ -1 +1,2 @@ -Modules \ No newline at end of file +Modules +file-blob-storing \ No newline at end of file diff --git a/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/LY.MicroService.WorkflowManagement.HttpApi.Host.csproj b/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/LY.MicroService.WorkflowManagement.HttpApi.Host.csproj index 87aa55abd..d624a7ca9 100644 --- a/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/LY.MicroService.WorkflowManagement.HttpApi.Host.csproj +++ b/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/LY.MicroService.WorkflowManagement.HttpApi.Host.csproj @@ -44,6 +44,7 @@ + diff --git a/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/WorkflowManagementHttpApiHostModule.Configure.cs b/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/WorkflowManagementHttpApiHostModule.Configure.cs index 38284fa6f..560230193 100644 --- a/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/WorkflowManagementHttpApiHostModule.Configure.cs +++ b/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/WorkflowManagementHttpApiHostModule.Configure.cs @@ -1,6 +1,7 @@ using LINGYUN.Abp.ExceptionHandling; using LINGYUN.Abp.ExceptionHandling.Emailing; using LINGYUN.Abp.Serilog.Enrichers.Application; +using LINGYUN.Abp.BlobStoring.OssManagement; using Medallion.Threading; using Medallion.Threading.Redis; using Microsoft.AspNetCore.Authentication.JwtBearer; @@ -15,6 +16,7 @@ using System.Text.Encodings.Web; using System.Text.Unicode; using Volo.Abp; using Volo.Abp.Auditing; +using Volo.Abp.BlobStoring; using Volo.Abp.Caching; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.Json; @@ -23,6 +25,7 @@ using Volo.Abp.Localization; using Volo.Abp.MultiTenancy; using Volo.Abp.Uow; using Volo.Abp.VirtualFileSystem; +using LINGYUN.Abp.WorkflowCore.Components; namespace LY.MicroService.WorkflowManagement { @@ -39,6 +42,21 @@ namespace LY.MicroService.WorkflowManagement services.AddSingleton(_ => new RedisDistributedSynchronizationProvider(redis.GetDatabase())); } + private void ConfigureBlobStoring(IServiceCollection services, IConfiguration configuration) + { + Configure(options => + { + services.ExecutePreConfiguredActions(options); + options.Containers.Configure((containerConfiguration) => + { + containerConfiguration.UseOssManagement(config => + { + config.Bucket = configuration[OssManagementBlobProviderConfigurationNames.Bucket] ?? "workflow"; + }); + }); + }); + } + private void ConfigureDbContext() { // 配置Ef diff --git a/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/WorkflowManagementHttpApiHostModule.cs b/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/WorkflowManagementHttpApiHostModule.cs index 601efa812..f27795517 100644 --- a/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/WorkflowManagementHttpApiHostModule.cs +++ b/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/WorkflowManagementHttpApiHostModule.cs @@ -1,4 +1,5 @@ using LINGYUN.Abp.AuditLogging.Elasticsearch; +using LINGYUN.Abp.BlobStoring.OssManagement; using LINGYUN.Abp.ExceptionHandling.Emailing; using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore; using LINGYUN.Abp.MultiTenancy.DbFinder; @@ -39,6 +40,7 @@ namespace LY.MicroService.WorkflowManagement typeof(AbpAuditLoggingElasticsearchModule), typeof(AbpAspNetCoreSerilogModule), typeof(AbpEventBusRabbitMqModule), + typeof(AbpBlobStoringOssManagementModule), typeof(WorkflowManagementApplicationModule), typeof(WorkflowManagementHttpApiModule), typeof(WorkflowManagementEntityFrameworkCoreModule), @@ -84,6 +86,7 @@ namespace LY.MicroService.WorkflowManagement ConfigureAuditing(configuration); ConfigureMultiTenancy(configuration); ConfigureSwagger(context.Services); + ConfigureBlobStoring(context.Services, configuration); ConfigureDistributedLock(context.Services, configuration); ConfigureSecurity(context.Services, configuration, hostingEnvironment.IsDevelopment()); } diff --git a/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/appsettings.Development.json b/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/appsettings.Development.json index 458c54540..b09ff9602 100644 --- a/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/appsettings.Development.json +++ b/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/appsettings.Development.json @@ -20,7 +20,13 @@ "AbpSettingManagement": "Server=127.0.0.1;Database=Platform;User Id=root;Password=123456", "AbpTenantManagement": "Server=127.0.0.1;Database=Platform;User Id=root;Password=123456" }, - "RemoteServices": {}, + "RemoteServices": { + "AbpOssManagement": { + "BaseUrl": "http://127.0.0.1:30025", + "IdentityClient": "InternalServiceClient", + "UseCurrentAccessToken": false + } + }, "IdentityClients": { "InternalServiceClient": { "Authority": "http://127.0.0.1:44385", @@ -31,13 +37,16 @@ "ClientSecret": "1q2w3E*" } }, + "OssManagement": { + "Bucket": "workflow" + }, "RabbitMQ": { "Connections": { "AbpWorkflowCore": { "HostName": "127.0.0.1", "Port": 5672, "UserName": "admin", - "Password": "123456", + "Password": "662874", "VirtualHost": "/" } },