Browse Source

feat(oss): add public/private file management api

pull/327/head
cKey 4 years ago
parent
commit
a2d478c993
  1. 739
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Aliyun/LINGYUN/Abp/OssManagement/Aliyun/AliyunOssContainer.cs
  2. 4
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN.Abp.OssManagement.Application.Contracts.csproj
  3. 24
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/AbpOssManagementApplicationContractsModule.cs
  4. 75
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/Features/AbpOssManagementFeatureDefinitionProvider.cs
  5. 41
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/Features/AbpOssManagementFeatureNames.cs
  6. 5
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN.Abp.OssManagement.Application.csproj
  7. 50
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/AbpOssManagementApplicationModule.cs
  8. 28
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/OssManagementApplicationServiceBase.cs
  9. 217
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/OssObjectAppService.cs
  10. 83
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/PublicFileAppService.cs
  11. 5
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN.Abp.OssManagement.Domain.Shared.csproj
  12. 72
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/AbpOssManagementDomainSharedModule.cs
  13. 1
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Localization/Resources/en.json
  14. 1
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Localization/Resources/zh-Hans.json
  15. 35
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/OssManagementErrorCodes.cs
  16. 49
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain/LINGYUN/Abp/OssManagement/AbpOssManagementDomainModule.cs
  17. 36
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.FileSystem/LINGYUN/Abp/OssManagement/FileSystem/AbpOssManagementFileSystemModule.cs
  18. 15
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.FileSystem/LINGYUN/Abp/OssManagement/FileSystem/FileSystemOssContainer.cs
  19. 96
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.FileSystem/LINGYUN/Abp/OssManagement/FileSystem/FileSystemOssContainerFactory.cs
  20. 1
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN.Abp.OssManagement.HttpApi.csproj
  21. 68
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/AbpOssManagementHttpApiModule.cs
  22. 96
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/FileValidater.cs
  23. 9
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/IFileValidater.cs
  24. 4
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/StaticFilesController.cs
  25. 12
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/UploadOssObjectInput.cs
  26. 20
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.SettingManagement/AbpOssManagementSettingManagementModule.cs
  27. 101
      aspnet-core/modules/oss-management/README.md
  28. 675
      aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/AppPlatformHttpApiHostModule.cs

739
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Aliyun/LINGYUN/Abp/OssManagement/Aliyun/AliyunOssContainer.cs

@ -1,369 +1,370 @@
using Aliyun.OSS; using Aliyun.OSS;
using LINGYUN.Abp.BlobStoring.Aliyun; using LINGYUN.Abp.BlobStoring.Aliyun;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.OssManagement.Aliyun namespace LINGYUN.Abp.OssManagement.Aliyun
{ {
/// <summary> /// <summary>
/// Oss容器的阿里云实现 /// Oss容器的阿里云实现
/// </summary> /// </summary>
internal class AliyunOssContainer : IOssContainer internal class AliyunOssContainer : IOssContainer
{ {
protected ICurrentTenant CurrentTenant { get; } protected ICurrentTenant CurrentTenant { get; }
protected IOssClientFactory OssClientFactory { get; } protected IOssClientFactory OssClientFactory { get; }
public AliyunOssContainer( public AliyunOssContainer(
ICurrentTenant currentTenant, ICurrentTenant currentTenant,
IOssClientFactory ossClientFactory) IOssClientFactory ossClientFactory)
{ {
CurrentTenant = currentTenant; CurrentTenant = currentTenant;
OssClientFactory = ossClientFactory; OssClientFactory = ossClientFactory;
} }
public virtual async Task BulkDeleteObjectsAsync(BulkDeleteObjectRequest request) public virtual async Task BulkDeleteObjectsAsync(BulkDeleteObjectRequest request)
{ {
var ossClient = await CreateClientAsync(); var ossClient = await CreateClientAsync();
var path = GetBasePath(request.Path); var path = GetBasePath(request.Path);
var aliyunRequest = new DeleteObjectsRequest(request.Bucket, request.Objects.Select(x => x += path).ToList()); var aliyunRequest = new DeleteObjectsRequest(request.Bucket, request.Objects.Select(x => x += path).ToList());
ossClient.DeleteObjects(aliyunRequest); ossClient.DeleteObjects(aliyunRequest);
} }
public virtual async Task<OssContainer> CreateAsync(string name) public virtual async Task<OssContainer> CreateAsync(string name)
{ {
var ossClient = await CreateClientAsync(); var ossClient = await CreateClientAsync();
if (BucketExists(ossClient, name)) if (BucketExists(ossClient, name))
{ {
throw new BusinessException(code: OssManagementErrorCodes.ContainerAlreadyExists); throw new BusinessException(code: OssManagementErrorCodes.ContainerAlreadyExists);
} }
var bucket = ossClient.CreateBucket(name); var bucket = ossClient.CreateBucket(name);
return new OssContainer( return new OssContainer(
bucket.Name, bucket.Name,
bucket.CreationDate, bucket.CreationDate,
0L, 0L,
bucket.CreationDate, bucket.CreationDate,
new Dictionary<string, string> new Dictionary<string, string>
{ {
{ "Id", bucket.Owner?.Id }, { "Id", bucket.Owner?.Id },
{ "DisplayName", bucket.Owner?.DisplayName } { "DisplayName", bucket.Owner?.DisplayName }
}); });
} }
public virtual async Task<OssObject> CreateObjectAsync(CreateOssObjectRequest request) public virtual async Task<OssObject> CreateObjectAsync(CreateOssObjectRequest request)
{ {
var ossClient = await CreateClientAsync(); var ossClient = await CreateClientAsync();
var objectPath = GetBasePath(request.Path); var objectPath = GetBasePath(request.Path);
var objectName = objectPath.IsNullOrWhiteSpace() var objectName = objectPath.IsNullOrWhiteSpace()
? request.Object ? request.Object
: objectPath + request.Object; : objectPath + request.Object;
if (!request.Overwrite && ObjectExists(ossClient, request.Bucket, objectName)) if (!request.Overwrite && ObjectExists(ossClient, request.Bucket, objectName))
{ {
throw new BusinessException(code: OssManagementErrorCodes.ObjectAlreadyExists); throw new BusinessException(code: OssManagementErrorCodes.ObjectAlreadyExists);
} }
// 当一个对象名称是以 / 结尾时,不论该对象是否存有数据,都以目录的形式存在 // 当一个对象名称是以 / 结尾时,不论该对象是否存有数据,都以目录的形式存在
// 详情见:https://help.aliyun.com/document_detail/31910.html // 详情见:https://help.aliyun.com/document_detail/31910.html
if (objectName.EndsWith("/") && if (objectName.EndsWith("/") &&
request.Content.IsNullOrEmpty()) request.Content.IsNullOrEmpty())
{ {
var emptyStream = new MemoryStream(); var emptyStream = new MemoryStream();
var emptyData = System.Text.Encoding.UTF8.GetBytes(""); var emptyData = System.Text.Encoding.UTF8.GetBytes("");
await emptyStream.WriteAsync(emptyData, 0, emptyData.Length); await emptyStream.WriteAsync(emptyData, 0, emptyData.Length);
request.SetContent(emptyStream); request.SetContent(emptyStream);
} }
// 没有bucket则创建 // 没有bucket则创建
if (!BucketExists(ossClient, request.Bucket)) if (!BucketExists(ossClient, request.Bucket))
{ {
ossClient.CreateBucket(request.Bucket); ossClient.CreateBucket(request.Bucket);
} }
var aliyunObjectRequest = new PutObjectRequest(request.Bucket, objectName, request.Content) var aliyunObjectRequest = new PutObjectRequest(request.Bucket, objectName, request.Content)
{ {
Metadata = new ObjectMetadata() Metadata = new ObjectMetadata()
}; };
if (request.ExpirationTime.HasValue) if (request.ExpirationTime.HasValue)
{ {
aliyunObjectRequest.Metadata.ExpirationTime = DateTime.Now.Add(request.ExpirationTime.Value); aliyunObjectRequest.Metadata.ExpirationTime = DateTime.Now.Add(request.ExpirationTime.Value);
} }
var aliyunObject = ossClient.PutObject(aliyunObjectRequest); var aliyunObject = ossClient.PutObject(aliyunObjectRequest);
var ossObject = new OssObject( var ossObject = new OssObject(
!objectPath.IsNullOrWhiteSpace() !objectPath.IsNullOrWhiteSpace()
? objectName.Replace(objectPath, "") ? objectName.Replace(objectPath, "")
: objectName, : objectName,
objectPath, objectPath,
DateTime.Now, DateTime.Now,
aliyunObject.ContentLength, aliyunObject.ContentLength,
DateTime.Now, DateTime.Now,
aliyunObject.ResponseMetadata, aliyunObject.ResponseMetadata,
objectName.EndsWith("/") // 名称结尾是 / 符号的则为目录:https://help.aliyun.com/document_detail/31910.html objectName.EndsWith("/") // 名称结尾是 / 符号的则为目录:https://help.aliyun.com/document_detail/31910.html
) )
{ {
FullName = objectName FullName = objectName
}; };
if (!Equals(request.Content, Stream.Null)) if (!Equals(request.Content, Stream.Null))
{ {
request.Content.Seek(0, SeekOrigin.Begin); request.Content.Seek(0, SeekOrigin.Begin);
ossObject.SetContent(request.Content); ossObject.SetContent(request.Content);
} }
return ossObject; return ossObject;
} }
public virtual async Task DeleteAsync(string name) public virtual async Task DeleteAsync(string name)
{ {
var ossClient = await CreateClientAsync(); // 阿里云oss在控制台设置即可,无需改变
var ossClient = await CreateClientAsync();
if (BucketExists(ossClient, name))
{ if (BucketExists(ossClient, name))
ossClient.DeleteBucket(name); {
} ossClient.DeleteBucket(name);
} }
}
public virtual async Task DeleteObjectAsync(GetOssObjectRequest request)
{ public virtual async Task DeleteObjectAsync(GetOssObjectRequest request)
var ossClient = await CreateClientAsync(); {
var ossClient = await CreateClientAsync();
var objectPath = GetBasePath(request.Path);
var objectPath = GetBasePath(request.Path);
var objectName = objectPath.IsNullOrWhiteSpace()
? request.Object var objectName = objectPath.IsNullOrWhiteSpace()
: objectPath + request.Object; ? request.Object
: objectPath + request.Object;
if (BucketExists(ossClient, request.Bucket) &&
ObjectExists(ossClient, request.Bucket, objectName)) if (BucketExists(ossClient, request.Bucket) &&
{ ObjectExists(ossClient, request.Bucket, objectName))
var objectListing = ossClient.ListObjects(request.Bucket, objectName); {
if (objectListing.CommonPrefixes.Any() || var objectListing = ossClient.ListObjects(request.Bucket, objectName);
objectListing.ObjectSummaries.Any()) if (objectListing.CommonPrefixes.Any() ||
{ objectListing.ObjectSummaries.Any())
throw new BusinessException(code: OssManagementErrorCodes.ObjectDeleteWithNotEmpty); {
// throw new ObjectDeleteWithNotEmptyException("00201", $"Can't not delete oss object {request.Object}, because it is not empty!"); throw new BusinessException(code: OssManagementErrorCodes.ObjectDeleteWithNotEmpty);
} // throw new ObjectDeleteWithNotEmptyException("00201", $"Can't not delete oss object {request.Object}, because it is not empty!");
ossClient.DeleteObject(request.Bucket, objectName); }
} ossClient.DeleteObject(request.Bucket, objectName);
} }
}
public virtual async Task<bool> ExistsAsync(string name)
{ public virtual async Task<bool> ExistsAsync(string name)
var ossClient = await CreateClientAsync(); {
var ossClient = await CreateClientAsync();
return BucketExists(ossClient, name);
} return BucketExists(ossClient, name);
}
public virtual async Task<OssContainer> GetAsync(string name)
{ public virtual async Task<OssContainer> GetAsync(string name)
var ossClient = await CreateClientAsync(); {
if (!BucketExists(ossClient, name)) var ossClient = await CreateClientAsync();
{ if (!BucketExists(ossClient, name))
throw new BusinessException(code: OssManagementErrorCodes.ContainerNotFound); {
// throw new ContainerNotFoundException($"Can't not found container {name} in aliyun blob storing"); throw new BusinessException(code: OssManagementErrorCodes.ContainerNotFound);
} // throw new ContainerNotFoundException($"Can't not found container {name} in aliyun blob storing");
var bucket = ossClient.GetBucketInfo(name); }
var bucket = ossClient.GetBucketInfo(name);
return new OssContainer(
bucket.Bucket.Name, return new OssContainer(
bucket.Bucket.CreationDate, bucket.Bucket.Name,
0L, bucket.Bucket.CreationDate,
bucket.Bucket.CreationDate, 0L,
new Dictionary<string, string> bucket.Bucket.CreationDate,
{ new Dictionary<string, string>
{ "Id", bucket.Bucket.Owner?.Id }, {
{ "DisplayName", bucket.Bucket.Owner?.DisplayName } { "Id", bucket.Bucket.Owner?.Id },
}); { "DisplayName", bucket.Bucket.Owner?.DisplayName }
} });
}
public virtual async Task<OssObject> GetObjectAsync(GetOssObjectRequest request)
{ public virtual async Task<OssObject> GetObjectAsync(GetOssObjectRequest request)
var ossClient = await CreateClientAsync(); {
if (!BucketExists(ossClient, request.Bucket)) var ossClient = await CreateClientAsync();
{ if (!BucketExists(ossClient, request.Bucket))
throw new BusinessException(code: OssManagementErrorCodes.ContainerNotFound); {
// throw new ContainerNotFoundException($"Can't not found container {request.Bucket} in aliyun blob storing"); throw new BusinessException(code: OssManagementErrorCodes.ContainerNotFound);
} // throw new ContainerNotFoundException($"Can't not found container {request.Bucket} in aliyun blob storing");
}
var objectPath = GetBasePath(request.Path);
var objectName = objectPath.IsNullOrWhiteSpace() var objectPath = GetBasePath(request.Path);
? request.Object var objectName = objectPath.IsNullOrWhiteSpace()
: objectPath + request.Object; ? request.Object
: objectPath + request.Object;
if (!ObjectExists(ossClient, request.Bucket, objectName))
{ if (!ObjectExists(ossClient, request.Bucket, objectName))
throw new BusinessException(code: OssManagementErrorCodes.ObjectNotFound); {
// throw new ContainerNotFoundException($"Can't not found object {objectName} in container {request.Bucket} with aliyun blob storing"); throw new BusinessException(code: OssManagementErrorCodes.ObjectNotFound);
} // throw new ContainerNotFoundException($"Can't not found object {objectName} in container {request.Bucket} with aliyun blob storing");
}
var aliyunOssObjectRequest = new GetObjectRequest(request.Bucket, objectName, request.Process);
var aliyunOssObject = ossClient.GetObject(aliyunOssObjectRequest); var aliyunOssObjectRequest = new GetObjectRequest(request.Bucket, objectName, request.Process);
var ossObject = new OssObject( var aliyunOssObject = ossClient.GetObject(aliyunOssObjectRequest);
!objectPath.IsNullOrWhiteSpace() var ossObject = new OssObject(
? aliyunOssObject.Key.Replace(objectPath, "") !objectPath.IsNullOrWhiteSpace()
: aliyunOssObject.Key, ? aliyunOssObject.Key.Replace(objectPath, "")
request.Path, : aliyunOssObject.Key,
aliyunOssObject.Metadata.LastModified, request.Path,
aliyunOssObject.Metadata.ContentLength, aliyunOssObject.Metadata.LastModified,
aliyunOssObject.Metadata.LastModified, aliyunOssObject.Metadata.ContentLength,
aliyunOssObject.Metadata.UserMetadata, aliyunOssObject.Metadata.LastModified,
aliyunOssObject.Key.EndsWith("/")) aliyunOssObject.Metadata.UserMetadata,
{ aliyunOssObject.Key.EndsWith("/"))
FullName = aliyunOssObject.Key {
}; FullName = aliyunOssObject.Key
};
if (aliyunOssObject.IsSetResponseStream())
{ if (aliyunOssObject.IsSetResponseStream())
var memoryStream = new MemoryStream(); {
await aliyunOssObject.Content.CopyToAsync(memoryStream); var memoryStream = new MemoryStream();
memoryStream.Seek(0, SeekOrigin.Begin); await aliyunOssObject.Content.CopyToAsync(memoryStream);
ossObject.SetContent(memoryStream); memoryStream.Seek(0, SeekOrigin.Begin);
} ossObject.SetContent(memoryStream);
}
return ossObject;
} return ossObject;
}
public virtual async Task<GetOssContainersResponse> GetListAsync(GetOssContainersRequest request)
{ public virtual async Task<GetOssContainersResponse> GetListAsync(GetOssContainersRequest request)
var ossClient = await CreateClientAsync(); {
var ossClient = await CreateClientAsync();
var aliyunRequest = new ListBucketsRequest
{ var aliyunRequest = new ListBucketsRequest
Marker = request.Marker, {
Prefix = request.Prefix, Marker = request.Marker,
MaxKeys = request.MaxKeys Prefix = request.Prefix,
}; MaxKeys = request.MaxKeys
var bucketsResponse = ossClient.ListBuckets(aliyunRequest); };
var bucketsResponse = ossClient.ListBuckets(aliyunRequest);
return new GetOssContainersResponse(
bucketsResponse.Prefix, return new GetOssContainersResponse(
bucketsResponse.Marker, bucketsResponse.Prefix,
bucketsResponse.NextMaker, bucketsResponse.Marker,
bucketsResponse.MaxKeys ?? 0, bucketsResponse.NextMaker,
bucketsResponse.Buckets bucketsResponse.MaxKeys ?? 0,
.Select(x => new OssContainer( bucketsResponse.Buckets
x.Name, .Select(x => new OssContainer(
x.CreationDate, x.Name,
0L, x.CreationDate,
x.CreationDate, 0L,
new Dictionary<string, string> x.CreationDate,
{ new Dictionary<string, string>
{ "Id", x.Owner?.Id }, {
{ "DisplayName", x.Owner?.DisplayName } { "Id", x.Owner?.Id },
})) { "DisplayName", x.Owner?.DisplayName }
.ToList()); }))
} .ToList());
}
public virtual async Task<GetOssObjectsResponse> GetObjectsAsync(GetOssObjectsRequest request)
{ public virtual async Task<GetOssObjectsResponse> GetObjectsAsync(GetOssObjectsRequest request)
{
var ossClient = await CreateClientAsync();
var ossClient = await CreateClientAsync();
var objectPath = GetBasePath(request.Prefix);
var marker = !objectPath.IsNullOrWhiteSpace() && !request.Marker.IsNullOrWhiteSpace() var objectPath = GetBasePath(request.Prefix);
? request.Marker.Replace(objectPath, "") var marker = !objectPath.IsNullOrWhiteSpace() && !request.Marker.IsNullOrWhiteSpace()
: request.Marker; ? request.Marker.Replace(objectPath, "")
var aliyunRequest = new ListObjectsRequest(request.BucketName) : request.Marker;
{ var aliyunRequest = new ListObjectsRequest(request.BucketName)
Marker = !marker.IsNullOrWhiteSpace() ? objectPath + marker : marker, {
Prefix = objectPath, Marker = !marker.IsNullOrWhiteSpace() ? objectPath + marker : marker,
MaxKeys = request.MaxKeys, Prefix = objectPath,
EncodingType = request.EncodingType, MaxKeys = request.MaxKeys,
Delimiter = request.Delimiter EncodingType = request.EncodingType,
}; Delimiter = request.Delimiter
var objectsResponse = ossClient.ListObjects(aliyunRequest); };
var objectsResponse = ossClient.ListObjects(aliyunRequest);
var ossObjects = objectsResponse.ObjectSummaries
.Where(x => !x.Key.Equals(objectsResponse.Prefix))// 过滤当前的目录返回值 var ossObjects = objectsResponse.ObjectSummaries
.Select(x => new OssObject( .Where(x => !x.Key.Equals(objectsResponse.Prefix))// 过滤当前的目录返回值
!objectPath.IsNullOrWhiteSpace() && !x.Key.Equals(objectPath) .Select(x => new OssObject(
? x.Key.Replace(objectPath, "") !objectPath.IsNullOrWhiteSpace() && !x.Key.Equals(objectPath)
: x.Key, // 去除目录名称 ? x.Key.Replace(objectPath, "")
request.Prefix, : x.Key, // 去除目录名称
x.LastModified, request.Prefix,
x.Size, x.LastModified,
x.LastModified, x.Size,
new Dictionary<string, string> x.LastModified,
{ new Dictionary<string, string>
{ "Id", x.Owner?.Id }, {
{ "DisplayName", x.Owner?.DisplayName } { "Id", x.Owner?.Id },
}, { "DisplayName", x.Owner?.DisplayName }
x.Key.EndsWith("/")) },
{ x.Key.EndsWith("/"))
FullName = x.Key {
}) FullName = x.Key
.ToList(); })
// 当 Delimiter 为 / 时, objectsResponse.CommonPrefixes 可用于代表层级目录 .ToList();
if (objectsResponse.CommonPrefixes.Any()) // 当 Delimiter 为 / 时, objectsResponse.CommonPrefixes 可用于代表层级目录
{ if (objectsResponse.CommonPrefixes.Any())
ossObjects.InsertRange(0, {
objectsResponse.CommonPrefixes ossObjects.InsertRange(0,
.Select(x => new OssObject( objectsResponse.CommonPrefixes
x.Replace(objectPath, ""), .Select(x => new OssObject(
request.Prefix, x.Replace(objectPath, ""),
null, request.Prefix,
0L, null,
null, 0L,
null, null,
true))); null,
} true)));
// 排序 }
// TODO: 是否需要客户端来排序 // 排序
ossObjects.Sort(new OssObjectComparer()); // TODO: 是否需要客户端来排序
ossObjects.Sort(new OssObjectComparer());
return new GetOssObjectsResponse(
objectsResponse.BucketName, return new GetOssObjectsResponse(
request.Prefix, objectsResponse.BucketName,
marker, request.Prefix,
!objectPath.IsNullOrWhiteSpace() && !objectsResponse.NextMarker.IsNullOrWhiteSpace() marker,
? objectsResponse.NextMarker.Replace(objectPath, "") !objectPath.IsNullOrWhiteSpace() && !objectsResponse.NextMarker.IsNullOrWhiteSpace()
: objectsResponse.NextMarker, ? objectsResponse.NextMarker.Replace(objectPath, "")
objectsResponse.Delimiter, : objectsResponse.NextMarker,
objectsResponse.MaxKeys, objectsResponse.Delimiter,
ossObjects); objectsResponse.MaxKeys,
} ossObjects);
}
protected virtual string GetBasePath(string path)
{ protected virtual string GetBasePath(string path)
string objectPath = ""; {
if (CurrentTenant.Id == null) string objectPath = "";
{ if (CurrentTenant.Id == null)
objectPath += "host/"; {
} objectPath += "host/";
else }
{ else
objectPath += "tenants/" + CurrentTenant.Id.Value.ToString("D"); {
} objectPath += "tenants/" + CurrentTenant.Id.Value.ToString("D");
}
objectPath += path ?? "";
objectPath += path ?? "";
return objectPath.EnsureEndsWith('/');
} return objectPath.EnsureEndsWith('/');
}
protected virtual bool BucketExists(IOss client, string bucketName)
{ protected virtual bool BucketExists(IOss client, string bucketName)
return client.DoesBucketExist(bucketName); {
} return client.DoesBucketExist(bucketName);
}
protected virtual bool ObjectExists(IOss client, string bucketName, string objectName)
{ protected virtual bool ObjectExists(IOss client, string bucketName, string objectName)
return client.DoesObjectExist(bucketName, objectName); {
} return client.DoesObjectExist(bucketName, objectName);
}
protected virtual async Task<IOss> CreateClientAsync()
{ protected virtual async Task<IOss> CreateClientAsync()
return await OssClientFactory.CreateAsync<AbpOssManagementContainer>(); {
} return await OssClientFactory.CreateAsync<AbpOssManagementContainer>();
} }
} }
}

4
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN.Abp.OssManagement.Application.Contracts.csproj

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
@ -8,7 +8,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Application" Version="4.4.0" /> <PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="4.4.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

24
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/AbpOssManagementApplicationContractsModule.cs

@ -1,12 +1,12 @@
using Volo.Abp.Application; using Volo.Abp.Application;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
namespace LINGYUN.Abp.OssManagement namespace LINGYUN.Abp.OssManagement
{ {
[DependsOn( [DependsOn(
typeof(AbpOssManagementDomainSharedModule), typeof(AbpOssManagementDomainSharedModule),
typeof(AbpDddApplicationModule))] typeof(AbpDddApplicationContractsModule))]
public class AbpOssManagementApplicationContractsModule : AbpModule public class AbpOssManagementApplicationContractsModule : AbpModule
{ {
} }
} }

75
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/Features/AbpOssManagementFeatureDefinitionProvider.cs

@ -1,75 +0,0 @@
using LINGYUN.Abp.OssManagement.Localization;
using Volo.Abp.Features;
using Volo.Abp.Localization;
using Volo.Abp.Validation.StringValues;
namespace LINGYUN.Abp.OssManagement.Features
{
public class AbpOssManagementFeatureDefinitionProvider : FeatureDefinitionProvider
{
public override void Define(IFeatureDefinitionContext context)
{
var featureGroup = context.AddGroup(
name: AbpOssManagementFeatureNames.GroupName,
displayName: L("Features:OssManagement"));
var ossFeature = featureGroup.AddFeature(
name: AbpOssManagementFeatureNames.OssObject.Default,
defaultValue: true.ToString(),
displayName: L("Features:DisplayName:OssObject"),
description: L("Features:Description:OssObject"),
valueType: new ToggleStringValueType(new BooleanValueValidator()));
ossFeature.CreateChild(
name: AbpOssManagementFeatureNames.OssObject.DownloadFile,
defaultValue: false.ToString(),
displayName: L("Features:DisplayName:DownloadFile"),
description: L("Features:Description:DownloadFile"),
valueType: new ToggleStringValueType(new BooleanValueValidator()));
ossFeature.CreateChild(
name: AbpOssManagementFeatureNames.OssObject.DownloadLimit,
defaultValue: "1000",
displayName: L("Features:DisplayName:DownloadLimit"),
description: L("Features:Description:DownloadLimit"),
valueType: new FreeTextStringValueType(new NumericValueValidator(0, 100_0000))); // 上限100万次调用
ossFeature.CreateChild(
name: AbpOssManagementFeatureNames.OssObject.DownloadInterval,
defaultValue: "1",
displayName: L("Features:DisplayName:DownloadInterval"),
description: L("Features:Description:DownloadInterval"),
valueType: new FreeTextStringValueType(new NumericValueValidator(1, 12))); // 上限12月
ossFeature.CreateChild(
name: AbpOssManagementFeatureNames.OssObject.UploadFile,
defaultValue: true.ToString(),
displayName: L("Features:DisplayName:UploadFile"),
description: L("Features:Description:UploadFile"),
valueType: new ToggleStringValueType(new BooleanValueValidator()));
ossFeature.CreateChild(
name: AbpOssManagementFeatureNames.OssObject.UploadLimit,
defaultValue: "1000",
displayName: L("Features:DisplayName:UploadLimit"),
description: L("Features:Description:UploadLimit"),
valueType: new FreeTextStringValueType(new NumericValueValidator(0, 100_0000))); // 上限100万次调用
ossFeature.CreateChild(
name: AbpOssManagementFeatureNames.OssObject.UploadInterval,
defaultValue: "1",
displayName: L("Features:DisplayName:UploadInterval"),
description: L("Features:Description:UploadInterval"),
valueType: new FreeTextStringValueType(new NumericValueValidator(1, 12))); // 上限12月
// TODO: 此功能需要控制器协同,暂时不实现
//fileSystemFeature.CreateChild(
// name: AbpOssManagementFeatureNames.OssObject.MaxUploadFileCount,
// defaultValue: 1.ToString(),
// displayName: L("Features:DisplayName:MaxUploadFileCount"),
// description: L("Features:Description:MaxUploadFileCount"),
// valueType: new FreeTextStringValueType(new NumericValueValidator(1, 10)));
}
protected ILocalizableString L(string name)
{
return LocalizableString.Create<AbpOssManagementResource>(name);
}
}
}

41
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/Features/AbpOssManagementFeatureNames.cs

@ -1,41 +0,0 @@
namespace LINGYUN.Abp.OssManagement.Features
{
public class AbpOssManagementFeatureNames
{
public const string GroupName = "AbpOssManagement";
public class OssObject
{
public const string Default = GroupName + ".OssObject";
/// <summary>
/// 下载文件功能
/// </summary>
public const string DownloadFile = Default + ".DownloadFile";
/// <summary>
/// 下载文件功能限制次数
/// </summary>
public const string DownloadLimit = Default + ".DownloadLimit";
/// <summary>
/// 下载文件功能限制次数周期
/// </summary>
public const string DownloadInterval = Default + ".DownloadInterval";
/// <summary>
/// 上传文件功能
/// </summary>
public const string UploadFile = Default + ".UploadFile";
/// <summary>
/// 上传文件功能限制次数
/// </summary>
public const string UploadLimit = Default + ".UploadLimit";
/// <summary>
/// 上传文件功能限制次数周期
/// </summary>
public const string UploadInterval = Default + ".UploadInterval";
/// <summary>
/// 最大上传文件
/// </summary>
public const string MaxUploadFileCount = Default + ".MaxUploadFileCount";
}
}
}

5
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN.Abp.OssManagement.Application.csproj

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
@ -9,9 +9,12 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.AutoMapper" Version="4.4.0" /> <PackageReference Include="Volo.Abp.AutoMapper" Version="4.4.0" />
<PackageReference Include="Volo.Abp.Ddd.Application" Version="4.4.0" />
<PackageReference Include="Volo.Abp.Caching" Version="4.4.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\common\LINGYUN.Abp.Settings\LINGYUN.Abp.Settings.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.OssManagement.Application.Contracts\LINGYUN.Abp.OssManagement.Application.Contracts.csproj" /> <ProjectReference Include="..\LINGYUN.Abp.OssManagement.Application.Contracts\LINGYUN.Abp.OssManagement.Application.Contracts.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.OssManagement.Domain\LINGYUN.Abp.OssManagement.Domain.csproj" /> <ProjectReference Include="..\LINGYUN.Abp.OssManagement.Domain\LINGYUN.Abp.OssManagement.Domain.csproj" />
</ItemGroup> </ItemGroup>

50
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/AbpOssManagementApplicationModule.cs

@ -1,23 +1,27 @@
using Volo.Abp.AutoMapper; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity; using Volo.Abp.Application;
using Microsoft.Extensions.DependencyInjection; using Volo.Abp.AutoMapper;
using Volo.Abp.Caching;
namespace LINGYUN.Abp.OssManagement using Volo.Abp.Modularity;
{
[DependsOn( namespace LINGYUN.Abp.OssManagement
typeof(AbpAutoMapperModule), {
typeof(AbpOssManagementDomainModule), [DependsOn(
typeof(AbpOssManagementApplicationContractsModule))] typeof(AbpOssManagementDomainModule),
public class AbpOssManagementApplicationModule : AbpModule typeof(AbpOssManagementApplicationContractsModule),
{ typeof(AbpCachingModule),
public override void ConfigureServices(ServiceConfigurationContext context) typeof(AbpAutoMapperModule),
{ typeof(AbpDddApplicationModule))]
context.Services.AddAutoMapperObjectMapper<AbpOssManagementApplicationModule>(); public class AbpOssManagementApplicationModule : AbpModule
{
Configure<AbpAutoMapperOptions>(options => public override void ConfigureServices(ServiceConfigurationContext context)
{ {
options.AddProfile<OssManagementApplicationAutoMapperProfile>(validate: true); context.Services.AddAutoMapperObjectMapper<AbpOssManagementApplicationModule>();
});
} Configure<AbpAutoMapperOptions>(options =>
} {
} options.AddProfile<OssManagementApplicationAutoMapperProfile>(validate: true);
});
}
}
}

28
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/OssManagementApplicationServiceBase.cs

@ -1,14 +1,14 @@
using LINGYUN.Abp.OssManagement.Localization; using LINGYUN.Abp.OssManagement.Localization;
using Volo.Abp.Application.Services; using Volo.Abp.Application.Services;
namespace LINGYUN.Abp.OssManagement namespace LINGYUN.Abp.OssManagement
{ {
public class OssManagementApplicationServiceBase : ApplicationService public abstract class OssManagementApplicationServiceBase : ApplicationService
{ {
protected OssManagementApplicationServiceBase() protected OssManagementApplicationServiceBase()
{ {
LocalizationResource = typeof(AbpOssManagementResource); LocalizationResource = typeof(AbpOssManagementResource);
ObjectMapperContext = typeof(AbpOssManagementApplicationModule); ObjectMapperContext = typeof(AbpOssManagementApplicationModule);
} }
} }
} }

217
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/OssObjectAppService.cs

@ -1,116 +1,101 @@
using LINGYUN.Abp.Features.LimitValidation; using LINGYUN.Abp.Features.LimitValidation;
using LINGYUN.Abp.OssManagement.Features; using LINGYUN.Abp.OssManagement.Features;
using LINGYUN.Abp.OssManagement.Permissions; using LINGYUN.Abp.OssManagement.Permissions;
using LINGYUN.Abp.OssManagement.Settings; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization; using System;
using System; using System.Collections.Generic;
using System.Collections.Generic; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations; using System.IO;
using System.IO; using System.Threading.Tasks;
using System.Linq; using Volo.Abp.Features;
using System.Threading.Tasks; using Volo.Abp.Validation;
using Volo.Abp.Features;
using Volo.Abp.IO; namespace LINGYUN.Abp.OssManagement
using Volo.Abp.Settings; {
using Volo.Abp.Validation; [Authorize(AbpOssManagementPermissions.OssObject.Default)]
public class OssObjectAppService : OssManagementApplicationServiceBase, IOssObjectAppService
namespace LINGYUN.Abp.OssManagement {
{ protected IFileValidater FileValidater { get; }
[Authorize(AbpOssManagementPermissions.OssObject.Default)] protected IOssContainerFactory OssContainerFactory { get; }
public class OssObjectAppService : OssManagementApplicationServiceBase, IOssObjectAppService
{ public OssObjectAppService(
protected IOssContainerFactory OssContainerFactory { get; } IFileValidater fileValidater,
IOssContainerFactory ossContainerFactory)
public OssObjectAppService( {
IOssContainerFactory ossContainerFactory) FileValidater = fileValidater;
{ OssContainerFactory = ossContainerFactory;
OssContainerFactory = ossContainerFactory; }
}
[Authorize(AbpOssManagementPermissions.OssObject.Create)]
[Authorize(AbpOssManagementPermissions.OssObject.Create)] [RequiresFeature(AbpOssManagementFeatureNames.OssObject.UploadFile)]
[RequiresFeature(AbpOssManagementFeatureNames.OssObject.UploadFile)] [RequiresLimitFeature(
[RequiresLimitFeature( AbpOssManagementFeatureNames.OssObject.UploadLimit,
AbpOssManagementFeatureNames.OssObject.UploadLimit, AbpOssManagementFeatureNames.OssObject.UploadInterval,
AbpOssManagementFeatureNames.OssObject.UploadInterval, LimitPolicy.Month)]
LimitPolicy.Month)] public virtual async Task<OssObjectDto> CreateAsync(CreateOssObjectInput input)
public virtual async Task<OssObjectDto> CreateAsync(CreateOssObjectInput input) {
{ if (!input.Content.IsNullOrEmpty())
if (!input.Content.IsNullOrEmpty()) {
{ await FileValidater.ValidationAsync(new UploadFile
// 检查文件大小 {
var fileSizeLimited = await SettingProvider TotalSize = input.Content.Length,
.GetAsync( FileName = input.Object
AbpOssManagementSettingNames.FileLimitLength, });
AbpOssManagementSettingNames.DefaultFileLimitLength); }
if (fileSizeLimited * 1024 * 1024 < input.Content.Length)
{ var oss = CreateOssContainer();
ThrowValidationException(L["UploadFileSizeBeyondLimit", fileSizeLimited], nameof(input.Content));
} var createOssObjectRequest = new CreateOssObjectRequest(
input.Bucket,
// 文件扩展名 input.Object,
var fileExtensionName = FileHelper.GetExtension(input.Object); input.Content,
var fileAllowExtension = await SettingProvider.GetOrNullAsync(AbpOssManagementSettingNames.AllowFileExtensions); input.Path,
// 检查文件扩展名 input.ExpirationTime)
if (!fileAllowExtension.Split(',') {
.Any(fe => fe.Equals(fileExtensionName, StringComparison.CurrentCultureIgnoreCase))) Overwrite = input.Overwrite
{ };
ThrowValidationException(L["NotAllowedFileExtensionName", fileExtensionName], "FileName"); var ossObject = await oss.CreateObjectAsync(createOssObjectRequest);
}
} return ObjectMapper.Map<OssObject, OssObjectDto>(ossObject);
}
var oss = CreateOssContainer();
[Authorize(AbpOssManagementPermissions.OssObject.Delete)]
var createOssObjectRequest = new CreateOssObjectRequest( public virtual async Task BulkDeleteAsync(BulkDeleteOssObjectInput input)
input.Bucket, {
input.Object, var oss = CreateOssContainer();
input.Content,
input.Path, await oss.BulkDeleteObjectsAsync(input.Bucket, input.Objects, input.Path);
input.ExpirationTime) }
{
Overwrite = input.Overwrite [Authorize(AbpOssManagementPermissions.OssObject.Delete)]
}; public virtual async Task DeleteAsync(GetOssObjectInput input)
var ossObject = await oss.CreateObjectAsync(createOssObjectRequest); {
var oss = CreateOssContainer();
return ObjectMapper.Map<OssObject, OssObjectDto>(ossObject);
} await oss.DeleteObjectAsync(input.Bucket, input.Object, input.Path);
}
[Authorize(AbpOssManagementPermissions.OssObject.Delete)]
public virtual async Task BulkDeleteAsync(BulkDeleteOssObjectInput input) public virtual async Task<OssObjectDto> GetAsync(GetOssObjectInput input)
{ {
var oss = CreateOssContainer(); var oss = CreateOssContainer();
await oss.BulkDeleteObjectsAsync(input.Bucket, input.Objects, input.Path); var ossObject = await oss.GetObjectAsync(input.Bucket, input.Object, input.Path);
}
return ObjectMapper.Map<OssObject, OssObjectDto>(ossObject);
[Authorize(AbpOssManagementPermissions.OssObject.Delete)] }
public virtual async Task DeleteAsync(GetOssObjectInput input)
{ protected virtual IOssContainer CreateOssContainer()
var oss = CreateOssContainer(); {
return OssContainerFactory.Create();
await oss.DeleteObjectAsync(input.Bucket, input.Object, input.Path); }
}
private static void ThrowValidationException(string message, string memberName)
public virtual async Task<OssObjectDto> GetAsync(GetOssObjectInput input) {
{ throw new AbpValidationException(message,
var oss = CreateOssContainer(); new List<ValidationResult>
{
var ossObject = await oss.GetObjectAsync(input.Bucket, input.Object, input.Path); new ValidationResult(message, new[] {memberName})
});
return ObjectMapper.Map<OssObject, OssObjectDto>(ossObject); }
} }
}
protected virtual IOssContainer CreateOssContainer()
{
return OssContainerFactory.Create();
}
private static void ThrowValidationException(string message, string memberName)
{
throw new AbpValidationException(message,
new List<ValidationResult>
{
new ValidationResult(message, new[] {memberName})
});
}
}
}

83
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/PublicFileAppService.cs

@ -1,89 +1,16 @@
using LINGYUN.Abp.Features.LimitValidation; namespace LINGYUN.Abp.OssManagement
using LINGYUN.Abp.OssManagement.Features;
using Microsoft.AspNetCore.Authorization;
using System.IO;
using System.Threading.Tasks;
using System.Web;
using Volo.Abp;
using Volo.Abp.Features;
using Volo.Abp.Users;
namespace LINGYUN.Abp.OssManagement
{ {
/// <summary> public class PublicFileAppService : FileAppServiceBase, IPublicFileAppService
/// 所有登录用户公开访问文件服务接口
/// bucket限制在users
/// path限制在用户id
/// </summary>
[Authorize]
// 不对外公开,仅通过控制器调用
[RemoteService(IsEnabled = false, IsMetadataEnabled = false)]
public class PublicFileAppService : OssManagementApplicationServiceBase, IPublicFileAppService
{ {
private readonly IFileValidater _fileValidater;
private readonly IOssContainerFactory _ossContainerFactory;
public PublicFileAppService( public PublicFileAppService(
IFileValidater fileValidater, IFileValidater fileValidater,
IOssContainerFactory ossContainerFactory) IOssContainerFactory ossContainerFactory)
: base(fileValidater, ossContainerFactory)
{ {
_fileValidater = fileValidater;
_ossContainerFactory = ossContainerFactory;
} }
protected override string GetCurrentBucket()
[RequiresFeature(AbpOssManagementFeatureNames.OssObject.UploadFile)]
[RequiresLimitFeature(
AbpOssManagementFeatureNames.OssObject.UploadLimit,
AbpOssManagementFeatureNames.OssObject.UploadInterval,
LimitPolicy.Month)]
public virtual async Task<OssObjectDto> UploadAsync(UploadPublicFileInput input)
{ {
await _fileValidater.ValidationAsync(new UploadFile return "public";
{
TotalSize = input.Content.Length,
FileName = input.Object
});
var oss = _ossContainerFactory.Create();
var createOssObjectRequest = new CreateOssObjectRequest(
"users",
HttpUtility.UrlDecode(input.Object),
input.Content,
GetCurrentUserPath(HttpUtility.UrlDecode(input.Path)))
{
Overwrite = input.Overwrite
};
var ossObject = await oss.CreateObjectAsync(createOssObjectRequest);
return ObjectMapper.Map<OssObject, OssObjectDto>(ossObject);
}
[RequiresFeature(AbpOssManagementFeatureNames.OssObject.DownloadFile)]
[RequiresLimitFeature(
AbpOssManagementFeatureNames.OssObject.DownloadLimit,
AbpOssManagementFeatureNames.OssObject.DownloadInterval,
LimitPolicy.Month)]
public virtual async Task<Stream> GetAsync(GetPublicFileInput input)
{
var ossObjectRequest = new GetOssObjectRequest(
"users", // 需要处理特殊字符
HttpUtility.UrlDecode(input.Name),
GetCurrentUserPath(HttpUtility.UrlDecode(input.Path)),
HttpUtility.UrlDecode(input.Process));
var ossContainer = _ossContainerFactory.Create();
var ossObject = await ossContainer.GetObjectAsync(ossObjectRequest);
return ossObject.Content;
}
private string GetCurrentUserPath(string path)
{
path = path.StartsWith("/") ? path.Substring(1) : path;
var userId = CurrentUser.GetId().ToString();
return path.StartsWith(userId) ? path : $"{userId}/{path}";
} }
} }
} }

5
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN.Abp.OssManagement.Domain.Shared.csproj

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
@ -18,7 +18,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.Validation" Version="4.4.0" /> <PackageReference Include="Volo.Abp.Features" Version="4.4.0" />
<PackageReference Include="Volo.Abp.Validation" Version="4.4.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

72
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/AbpOssManagementDomainSharedModule.cs

@ -1,36 +1,36 @@
using LINGYUN.Abp.OssManagement.Localization; using LINGYUN.Abp.OssManagement.Localization;
using Volo.Abp.Localization; using Volo.Abp.Features;
using Volo.Abp.Localization.ExceptionHandling; using Volo.Abp.Localization;
using Volo.Abp.Modularity; using Volo.Abp.Localization.ExceptionHandling;
using Volo.Abp.Validation; using Volo.Abp.Modularity;
using Volo.Abp.Validation.Localization; using Volo.Abp.Validation;
using Volo.Abp.VirtualFileSystem; using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.OssManagement namespace LINGYUN.Abp.OssManagement
{ {
[DependsOn(typeof(AbpValidationModule))] [DependsOn(
public class AbpOssManagementDomainSharedModule : AbpModule typeof(AbpFeaturesModule),
{ typeof(AbpValidationModule))]
public override void ConfigureServices(ServiceConfigurationContext context) public class AbpOssManagementDomainSharedModule : AbpModule
{ {
Configure<AbpVirtualFileSystemOptions>(options => public override void ConfigureServices(ServiceConfigurationContext context)
{ {
options.FileSets.AddEmbedded<AbpOssManagementDomainSharedModule>(); Configure<AbpVirtualFileSystemOptions>(options =>
}); {
options.FileSets.AddEmbedded<AbpOssManagementDomainSharedModule>();
Configure<AbpLocalizationOptions>(options => });
{
options.Resources Configure<AbpLocalizationOptions>(options =>
.Add<AbpOssManagementResource>("en") {
.AddBaseTypes( options.Resources
typeof(AbpValidationResource) .Add<AbpOssManagementResource>("en")
).AddVirtualJson("/LINGYUN/Abp/OssManagement/Localization/Resources"); .AddVirtualJson("/LINGYUN/Abp/OssManagement/Localization/Resources");
}); });
Configure<AbpExceptionLocalizationOptions>(options => Configure<AbpExceptionLocalizationOptions>(options =>
{ {
options.MapCodeNamespace(OssManagementErrorCodes.Namespace, typeof(AbpOssManagementResource)); options.MapCodeNamespace(OssManagementErrorCodes.Namespace, typeof(AbpOssManagementResource));
}); });
} }
} }
} }

1
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Localization/Resources/en.json

@ -1,6 +1,7 @@
{ {
"culture": "en", "culture": "en",
"texts": { "texts": {
"Abp.OssManagement:010000": "System definition containers cannot be deleted!",
"Abp.OssManagement:010001": "Cannot delete a container that has more than one object!", "Abp.OssManagement:010001": "Cannot delete a container that has more than one object!",
"Abp.OssManagement:010402": "The container name already exists!", "Abp.OssManagement:010402": "The container name already exists!",
"Abp.OssManagement:010404": "The queried container could not be found!", "Abp.OssManagement:010404": "The queried container could not be found!",

1
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Localization/Resources/zh-Hans.json

@ -1,6 +1,7 @@
{ {
"culture": "zh-Hans", "culture": "zh-Hans",
"texts": { "texts": {
"Abp.OssManagement:010000": "不能删除系统定义容器!",
"Abp.OssManagement:010001": "不能删除存在多个对象的容器!", "Abp.OssManagement:010001": "不能删除存在多个对象的容器!",
"Abp.OssManagement:010402": "容器名称已经存在!", "Abp.OssManagement:010402": "容器名称已经存在!",
"Abp.OssManagement:010404": "未能找到查询的容器!", "Abp.OssManagement:010404": "未能找到查询的容器!",

35
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/OssManagementErrorCodes.cs

@ -1,17 +1,18 @@
namespace LINGYUN.Abp.OssManagement namespace LINGYUN.Abp.OssManagement
{ {
public static class OssManagementErrorCodes public static class OssManagementErrorCodes
{ {
public const string Namespace = "Abp.OssManagement"; public const string Namespace = "Abp.OssManagement";
public const string ContainerDeleteWithNotEmpty = Namespace + ":010001"; public const string ContainerDeleteWithStatic = Namespace + ":010000";
public const string ContainerAlreadyExists = Namespace + ":010402"; public const string ContainerDeleteWithNotEmpty = Namespace + ":010001";
public const string ContainerNotFound = Namespace + ":010404"; public const string ContainerAlreadyExists = Namespace + ":010402";
public const string ContainerNotFound = Namespace + ":010404";
public const string ObjectDeleteWithNotEmpty = Namespace + ":020001";
public const string ObjectAlreadyExists = Namespace + ":020402"; public const string ObjectDeleteWithNotEmpty = Namespace + ":020001";
public const string ObjectNotFound = Namespace + ":020404"; public const string ObjectAlreadyExists = Namespace + ":020402";
public const string ObjectNotFound = Namespace + ":020404";
public const string OssNameHasTooLong = Namespace + ":000405";
} public const string OssNameHasTooLong = Namespace + ":000405";
} }
}

49
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain/LINGYUN/Abp/OssManagement/AbpOssManagementDomainModule.cs

@ -1,17 +1,32 @@
using LINGYUN.Abp.Features.LimitValidation; using LINGYUN.Abp.Features.LimitValidation;
using Volo.Abp.Domain; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity; using Microsoft.Extensions.Options;
using Volo.Abp.MultiTenancy; using Volo.Abp;
using Volo.Abp.Domain;
namespace LINGYUN.Abp.OssManagement using Volo.Abp.Modularity;
{ using Volo.Abp.MultiTenancy;
[DependsOn(
typeof(AbpDddDomainModule), namespace LINGYUN.Abp.OssManagement
typeof(AbpMultiTenancyModule), {
typeof(AbpFeaturesLimitValidationModule), [DependsOn(
typeof(AbpOssManagementDomainSharedModule) typeof(AbpOssManagementDomainSharedModule),
)] typeof(AbpDddDomainModule),
public class AbpOssManagementDomainModule : AbpModule typeof(AbpMultiTenancyModule),
{ typeof(AbpFeaturesLimitValidationModule)
} )]
} public class AbpOssManagementDomainModule : AbpModule
{
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
// TODO: 是否有必要自动创建容器
var ossOptions = context.ServiceProvider.GetRequiredService<IOptions<AbpOssManagementOptions>>().Value;
var ossFactory = context.ServiceProvider.GetRequiredService<IOssContainerFactory>();
var ossContainer = ossFactory.Create();
foreach (var bucket in ossOptions.StaticBuckets)
{
_ = ossContainer.CreateIfNotExistsAsync(bucket);
}
}
}
}

36
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.FileSystem/LINGYUN/Abp/OssManagement/FileSystem/AbpOssManagementFileSystemModule.cs

@ -1,17 +1,19 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.BlobStoring.FileSystem; using Microsoft.Extensions.Options;
using Volo.Abp.Modularity; using Volo.Abp;
using Volo.Abp.BlobStoring.FileSystem;
namespace LINGYUN.Abp.OssManagement.FileSystem using Volo.Abp.Modularity;
{
[DependsOn( namespace LINGYUN.Abp.OssManagement.FileSystem
typeof(AbpBlobStoringFileSystemModule), {
typeof(AbpOssManagementDomainModule))] [DependsOn(
public class AbpOssManagementFileSystemModule : AbpModule typeof(AbpBlobStoringFileSystemModule),
{ typeof(AbpOssManagementDomainModule))]
public override void ConfigureServices(ServiceConfigurationContext context) public class AbpOssManagementFileSystemModule : AbpModule
{ {
context.Services.AddTransient<IOssContainerFactory, FileSystemOssContainerFactory>(); public override void ConfigureServices(ServiceConfigurationContext context)
} {
} context.Services.AddTransient<IOssContainerFactory, FileSystemOssContainerFactory>();
} }
}
}

15
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.FileSystem/LINGYUN/Abp/OssManagement/FileSystem/FileSystemOssContainer.cs

@ -25,6 +25,7 @@ namespace LINGYUN.Abp.OssManagement.FileSystem
protected IBlobContainerConfigurationProvider ConfigurationProvider { get; } protected IBlobContainerConfigurationProvider ConfigurationProvider { get; }
protected IServiceProvider ServiceProvider { get; } protected IServiceProvider ServiceProvider { get; }
protected FileSystemOssOptions Options { get; } protected FileSystemOssOptions Options { get; }
protected AbpOssManagementOptions OssOptions { get; }
public FileSystemOssContainer( public FileSystemOssContainer(
ICurrentTenant currentTenant, ICurrentTenant currentTenant,
@ -32,7 +33,8 @@ namespace LINGYUN.Abp.OssManagement.FileSystem
IServiceProvider serviceProvider, IServiceProvider serviceProvider,
IBlobFilePathCalculator blobFilePathCalculator, IBlobFilePathCalculator blobFilePathCalculator,
IBlobContainerConfigurationProvider configurationProvider, IBlobContainerConfigurationProvider configurationProvider,
IOptions<FileSystemOssOptions> options) IOptions<FileSystemOssOptions> options,
IOptions<AbpOssManagementOptions> ossOptions)
{ {
CurrentTenant = currentTenant; CurrentTenant = currentTenant;
Environment = environment; Environment = environment;
@ -40,6 +42,7 @@ namespace LINGYUN.Abp.OssManagement.FileSystem
FilePathCalculator = blobFilePathCalculator; FilePathCalculator = blobFilePathCalculator;
ConfigurationProvider = configurationProvider; ConfigurationProvider = configurationProvider;
Options = options.Value; Options = options.Value;
OssOptions = ossOptions.Value;
} }
public virtual Task BulkDeleteObjectsAsync(BulkDeleteObjectRequest request) public virtual Task BulkDeleteObjectsAsync(BulkDeleteObjectRequest request)
@ -173,6 +176,8 @@ namespace LINGYUN.Abp.OssManagement.FileSystem
public virtual Task DeleteAsync(string name) public virtual Task DeleteAsync(string name)
{ {
CheckStaticBucket(name);
var filePath = CalculateFilePath(name); var filePath = CalculateFilePath(name);
if (!Directory.Exists(filePath)) if (!Directory.Exists(filePath))
{ {
@ -533,6 +538,14 @@ namespace LINGYUN.Abp.OssManagement.FileSystem
return blobPath; return blobPath;
} }
protected virtual void CheckStaticBucket(string bucket)
{
if (OssOptions.CheckStaticBucket(bucket))
{
throw new BusinessException(code: OssManagementErrorCodes.ContainerDeleteWithStatic);
}
}
private void ThrowOfPathHasTooLong(string path) private void ThrowOfPathHasTooLong(string path)
{ {
// Windows 133 260 // Windows 133 260

96
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.FileSystem/LINGYUN/Abp/OssManagement/FileSystem/FileSystemOssContainerFactory.cs

@ -1,46 +1,50 @@
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using System; using System;
using Volo.Abp.BlobStoring; using Volo.Abp.BlobStoring;
using Volo.Abp.BlobStoring.FileSystem; using Volo.Abp.BlobStoring.FileSystem;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.OssManagement.FileSystem namespace LINGYUN.Abp.OssManagement.FileSystem
{ {
public class FileSystemOssContainerFactory : IOssContainerFactory public class FileSystemOssContainerFactory : IOssContainerFactory
{ {
protected ICurrentTenant CurrentTenant { get; } protected ICurrentTenant CurrentTenant { get; }
protected IHostEnvironment Environment { get; } protected IHostEnvironment Environment { get; }
protected IServiceProvider ServiceProvider { get; } protected IServiceProvider ServiceProvider { get; }
protected IBlobFilePathCalculator FilePathCalculator { get; } protected IBlobFilePathCalculator FilePathCalculator { get; }
protected IBlobContainerConfigurationProvider ConfigurationProvider { get; } protected IBlobContainerConfigurationProvider ConfigurationProvider { get; }
protected IOptions<FileSystemOssOptions> Options { get; } protected IOptions<FileSystemOssOptions> Options { get; }
protected IOptions<AbpOssManagementOptions> OssOptions { get; }
public FileSystemOssContainerFactory(
ICurrentTenant currentTenant, public FileSystemOssContainerFactory(
IHostEnvironment environment, ICurrentTenant currentTenant,
IServiceProvider serviceProvider, IHostEnvironment environment,
IBlobFilePathCalculator blobFilePathCalculator, IServiceProvider serviceProvider,
IBlobContainerConfigurationProvider configurationProvider, IBlobFilePathCalculator blobFilePathCalculator,
IOptions<FileSystemOssOptions> options) IBlobContainerConfigurationProvider configurationProvider,
{ IOptions<FileSystemOssOptions> options,
Environment = environment; IOptions<AbpOssManagementOptions> ossOptions)
CurrentTenant = currentTenant; {
ServiceProvider = serviceProvider; Environment = environment;
FilePathCalculator = blobFilePathCalculator; CurrentTenant = currentTenant;
ConfigurationProvider = configurationProvider; ServiceProvider = serviceProvider;
Options = options; FilePathCalculator = blobFilePathCalculator;
} ConfigurationProvider = configurationProvider;
Options = options;
public IOssContainer Create() OssOptions = ossOptions;
{ }
return new FileSystemOssContainer(
CurrentTenant, public IOssContainer Create()
Environment, {
ServiceProvider, return new FileSystemOssContainer(
FilePathCalculator, CurrentTenant,
ConfigurationProvider, Environment,
Options); ServiceProvider,
} FilePathCalculator,
} ConfigurationProvider,
} Options,
OssOptions);
}
}
}

1
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN.Abp.OssManagement.HttpApi.csproj

@ -12,7 +12,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\common\LINGYUN.Abp.Settings\LINGYUN.Abp.Settings.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.OssManagement.Application.Contracts\LINGYUN.Abp.OssManagement.Application.Contracts.csproj" /> <ProjectReference Include="..\LINGYUN.Abp.OssManagement.Application.Contracts\LINGYUN.Abp.OssManagement.Application.Contracts.csproj" />
</ItemGroup> </ItemGroup>

68
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/AbpOssManagementHttpApiModule.cs

@ -1,21 +1,47 @@
using Microsoft.Extensions.DependencyInjection; using LINGYUN.Abp.OssManagement.Localization;
using Volo.Abp.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity; using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Authorization.Localization;
namespace LINGYUN.Abp.OssManagement using Volo.Abp.Localization;
{ using Volo.Abp.Modularity;
[DependsOn( using Volo.Abp.Validation.Localization;
typeof(AbpOssManagementApplicationContractsModule), using Volo.Abp.AspNetCore.Mvc.DataAnnotations;
typeof(AbpAspNetCoreMvcModule) using Volo.Abp.AspNetCore.Mvc.Localization;
)]
public class AbpOssManagementHttpApiModule : AbpModule namespace LINGYUN.Abp.OssManagement
{ {
public override void PreConfigureServices(ServiceConfigurationContext context) [DependsOn(
{ typeof(AbpOssManagementApplicationContractsModule),
PreConfigure<IMvcBuilder>(mvcBuilder => typeof(AbpAspNetCoreMvcModule)
{ )]
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpOssManagementHttpApiModule).Assembly); public class AbpOssManagementHttpApiModule : AbpModule
}); {
} public override void PreConfigureServices(ServiceConfigurationContext context)
} {
} PreConfigure<IMvcBuilder>(mvcBuilder =>
{
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpOssManagementHttpApiModule).Assembly);
});
PreConfigure<AbpMvcDataAnnotationsLocalizationOptions>(options =>
{
options.AddAssemblyResource(
typeof(AbpOssManagementResource),
typeof(AbpOssManagementApplicationContractsModule).Assembly);
});
}
//public override void ConfigureServices(ServiceConfigurationContext context)
//{
// Configure<AbpLocalizationOptions>(options =>
// {
// options.Resources
// .Get<AbpOssManagementResource>()
// .AddBaseTypes(
// typeof(AbpAuthorizationResource),
// typeof(AbpValidationResource)
// );
// });
//}
}
}

96
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/FileValidater.cs

@ -1,96 +0,0 @@
using LINGYUN.Abp.OssManagement.Localization;
using LINGYUN.Abp.OssManagement.Settings;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Localization;
using System;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
using Volo.Abp.IO;
using Volo.Abp.Settings;
namespace LINGYUN.Abp.OssManagement
{
public class FileValidater : IFileValidater, ISingletonDependency
{
private readonly IMemoryCache _cache;
private readonly ISettingProvider _settingProvider;
private readonly IServiceProvider _serviceProvider;
private readonly IStringLocalizer _stringLocalizer;
public FileValidater(
IMemoryCache cache,
ISettingProvider settingProvider,
IServiceProvider serviceProvider,
IStringLocalizer<AbpOssManagementResource> stringLocalizer)
{
_cache = cache;
_settingProvider = settingProvider;
_serviceProvider = serviceProvider;
_stringLocalizer = stringLocalizer;
}
public virtual async Task ValidationAsync(UploadOssObjectInput input)
{
var validation = await GetByCacheItemAsync();
if (validation.SizeLimit * 1024 * 1024 < input.TotalSize)
{
throw new UserFriendlyException(_stringLocalizer["UploadFileSizeBeyondLimit", validation.SizeLimit]);
}
var fileExtensionName = FileHelper.GetExtension(input.FileName);
if (!validation.AllowedExtensions
.Any(fe => fe.Equals(fileExtensionName, StringComparison.CurrentCultureIgnoreCase)))
{
throw new UserFriendlyException(_stringLocalizer["NotAllowedFileExtensionName", fileExtensionName]);
}
}
protected virtual async Task<FileValidation> GetByCacheItemAsync()
{
var fileValidation = _cache.Get<FileValidation>(FileValidation.CacheKey);
if (fileValidation == null)
{
fileValidation = await GetBySettingAsync();
_cache.Set(FileValidation.CacheKey,
fileValidation,
new MemoryCacheEntryOptions
{
AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(2)
});
}
return fileValidation;
}
protected virtual async Task<FileValidation> GetBySettingAsync()
{
var fileSizeLimited = await _settingProvider
.GetAsync(
AbpOssManagementSettingNames.FileLimitLength,
AbpOssManagementSettingNames.DefaultFileLimitLength);
var fileAllowExtension = await _settingProvider
.GetOrDefaultAsync(AbpOssManagementSettingNames.AllowFileExtensions, _serviceProvider);
return new FileValidation(fileSizeLimited, fileAllowExtension.Split(','));
}
}
public class FileValidation
{
public const string CacheKey = "Abp.OssManagement.FileValidation";
public long SizeLimit { get; set; }
public string[] AllowedExtensions { get; set; }
public FileValidation()
{
}
public FileValidation(
long sizeLimit,
string[] allowedExtensions)
{
SizeLimit = sizeLimit;
AllowedExtensions = allowedExtensions;
}
}
}

9
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/IFileValidater.cs

@ -1,9 +0,0 @@
using System.Threading.Tasks;
namespace LINGYUN.Abp.OssManagement
{
public interface IFileValidater
{
Task ValidationAsync(UploadOssObjectInput input);
}
}

4
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/StaticFilesController.cs

@ -1,7 +1,6 @@
using LINGYUN.Abp.OssManagement.Localization; using LINGYUN.Abp.OssManagement.Localization;
using LINGYUN.Abp.OssManagement.Permissions; using LINGYUN.Abp.OssManagement.Permissions;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
@ -15,9 +14,10 @@ using Volo.Abp.Validation;
namespace LINGYUN.Abp.OssManagement namespace LINGYUN.Abp.OssManagement
{ {
[RemoteService(Name = OssManagementRemoteServiceConsts.RemoteServiceName)]
[Area("oss-management")] [Area("oss-management")]
[Route("api/files/static")] [Route("api/files/static")]
[RemoteService(false)]
[ApiExplorerSettings(IgnoreApi = true)]
public class StaticFilesController : AbpController public class StaticFilesController : AbpController
{ {
private readonly IOssObjectAppService _ossObjectAppService; private readonly IOssObjectAppService _ossObjectAppService;

12
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/UploadOssObjectInput.cs

@ -3,18 +3,13 @@ using System.ComponentModel.DataAnnotations;
namespace LINGYUN.Abp.OssManagement namespace LINGYUN.Abp.OssManagement
{ {
public class UploadOssObjectInput public class UploadOssObjectInput : UploadFile
{ {
public string Bucket { get; set; } public string Bucket { get; set; }
public string Path { get; set; } public string Path { get; set; }
#region 配合Uplaoder 分块传输 #region 配合Uplaoder 分块传输
/// <summary> /// <summary>
/// 文件名
/// </summary>
[Required]
public string FileName { get; set; }
/// <summary>
/// 常规块大小 /// 常规块大小
/// </summary> /// </summary>
[Required] [Required]
@ -34,11 +29,6 @@ namespace LINGYUN.Abp.OssManagement
/// </summary> /// </summary>
[Required] [Required]
public int TotalChunks { get; set; } public int TotalChunks { get; set; }
/// <summary>
/// 总文件大小
/// </summary>
[Required]
public long TotalSize { get; set; }
#endregion #endregion

20
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.SettingManagement/AbpOssManagementSettingManagementModule.cs

@ -1,20 +0,0 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.OssManagement.SettingManagement
{
[DependsOn(
typeof(AbpOssManagementApplicationContractsModule),
typeof(AbpAspNetCoreMvcModule))]
public class AbpOssManagementSettingManagementModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<IMvcBuilder>(mvcBuilder =>
{
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpOssManagementSettingManagementModule).Assembly);
});
}
}
}

101
aspnet-core/modules/oss-management/README.md

@ -1,50 +1,51 @@
# Oss-Management # Oss-Management
File-Management更名为Oss-Management File-Management更名为Oss-Management
## 模块说明 ## 模块说明
### 基础模块 ### 基础模块
* [LINGYUN.Abp.OssManagement.Domain.Shared](./LINGYUN.Abp.OssManagement.Domain.Shared) 领域层公共模块,定义了错误代码、本地化、模块设置 * [LINGYUN.Abp.OssManagement.Domain.Shared](./LINGYUN.Abp.OssManagement.Domain.Shared) 领域层公共模块,定义了错误代码、本地化、模块设置
* [LINGYUN.Abp.OssManagement.Domain](./LINGYUN.Abp.OssManagement.Domain) 领域层模块,定义了抽象的Oss容器与对象管理接口 * [LINGYUN.Abp.OssManagement.Domain](./LINGYUN.Abp.OssManagement.Domain) 领域层模块,定义了抽象的Oss容器与对象管理接口
* [LINGYUN.Abp.OssManagement.Application.Contracts](./LINGYUN.Abp.OssManagement.Application.Contracts) 应用服务层公共模块,定义了管理Oss的外部接口、权限、功能限制策略 * [LINGYUN.Abp.OssManagement.Application.Contracts](./LINGYUN.Abp.OssManagement.Application.Contracts) 应用服务层公共模块,定义了管理Oss的外部接口、权限、功能限制策略
* [LINGYUN.Abp.OssManagement.Application](./LINGYUN.Abp.OssManagement.Application) 应用服务层实现,实现了Oss管理接口 * [LINGYUN.Abp.OssManagement.Application](./LINGYUN.Abp.OssManagement.Application) 应用服务层实现,实现了Oss管理接口
* [LINGYUN.Abp.OssManagement.HttpApi](./LINGYUN.Abp.OssManagement.HttpApi) RestApi实现,实现了独立的对外RestApi接口 * [LINGYUN.Abp.OssManagement.HttpApi](./LINGYUN.Abp.OssManagement.HttpApi) RestApi实现,实现了独立的对外RestApi接口
* [LINGYUN.Abp.OssManagement.SettingManagement](./LINGYUN.Abp.OssManagement.SettingManagement) 设置管理模块,对外暴露自身的设置管理,用于网关聚合 * [LINGYUN.Abp.OssManagement.SettingManagement](./LINGYUN.Abp.OssManagement.SettingManagement) 设置管理模块,对外暴露自身的设置管理,用于网关聚合
### 高阶模块 ### 高阶模块
* [LINGYUN.Abp.OssManagement.Aliyun](./LINGYUN.Abp.OssManagement.Aliyun) Oss管理的阿里云实现,实现了部分阿里云Oss服务的容器与对象管理 * [LINGYUN.Abp.OssManagement.Aliyun](./LINGYUN.Abp.OssManagement.Aliyun) Oss管理的阿里云实现,实现了部分阿里云Oss服务的容器与对象管理
* [LINGYUN.Abp.OssManagement.FileSystem](./LINGYUN.Abp.OssManagement.FileSystem) Oss管理的本地文件系统实现,实现了部分本地文件系统的容器(目录)与对象(文件/目录)管理 * [LINGYUN.Abp.OssManagement.FileSystem](./LINGYUN.Abp.OssManagement.FileSystem) Oss管理的本地文件系统实现,实现了部分本地文件系统的容器(目录)与对象(文件/目录)管理
* [LINGYUN.Abp.OssManagement.FileSystem.ImageSharp](./LINGYUN.Abp.OssManagement.FileSystem.ImageSharp) Oss本地对象的ImageSharp扩展,当前端传递需求处理对象时,此模块用于实现基于图形文件流的处理 * [LINGYUN.Abp.OssManagement.FileSystem.ImageSharp](./LINGYUN.Abp.OssManagement.FileSystem.ImageSharp) Oss本地对象的ImageSharp扩展,当前端传递需求处理对象时,此模块用于实现基于图形文件流的处理
### 权限定义 ### 权限定义
* AbpOssManagement.Container 授权对象是否允许访问容器(bucket) * AbpOssManagement.Container 授权对象是否允许访问容器(bucket)
* AbpOssManagement.Container.Create 授权对象是否允许创建容器(bucket) * AbpOssManagement.Container.Create 授权对象是否允许创建容器(bucket)
* AbpOssManagement.Container.Delete 授权对象是否允许删除容器(bucket) * AbpOssManagement.Container.Delete 授权对象是否允许删除容器(bucket)
* AbpOssManagement.OssObject 授权对象是否允许访问Oss对象 * AbpOssManagement.OssObject 授权对象是否允许访问Oss对象
* AbpOssManagement.OssObject.Create 授权对象是否允许创建Oss对象 * AbpOssManagement.OssObject.Create 授权对象是否允许创建Oss对象
* AbpOssManagement.OssObject.Delete 授权对象是否允许删除Oss对象 * AbpOssManagement.OssObject.Delete 授权对象是否允许删除Oss对象
* AbpOssManagement.OssObject.Download 授权对象是否允许下载Oss对象 * AbpOssManagement.OssObject.Download 授权对象是否允许下载Oss对象
### 功能定义 ### 功能定义
* AbpOssManagement.OssObject.DownloadFile 用户可以下载文件 * AbpOssManagement.OssObject.DownloadFile 用户可以下载文件
* AbpOssManagement.OssObject.DownloadLimit 用户在周期内允许下载文件的最大次数,范围0-1000000 * AbpOssManagement.OssObject.DownloadLimit 用户在周期内允许下载文件的最大次数,范围0-1000000
* AbpOssManagement.OssObject.DownloadInterval 用户限制下载文件次数的周期,时钟刻度:月,默认: 1,范围1-12 * AbpOssManagement.OssObject.DownloadInterval 用户限制下载文件次数的周期,时钟刻度:月,默认: 1,范围1-12
* AbpOssManagement.OssObject.UploadFile 用户可以上传文件 * AbpOssManagement.OssObject.UploadFile 用户可以上传文件
* AbpOssManagement.OssObject.UploadLimit 用户在周期内允许上传文件的最大次数,范围0-1000000 * AbpOssManagement.OssObject.UploadLimit 用户在周期内允许上传文件的最大次数,范围0-1000000
* AbpOssManagement.OssObject.UploadInterval 用户限制上传文件次数的周期,时钟刻度:月,默认: 1,范围1-12 * AbpOssManagement.OssObject.UploadInterval 用户限制上传文件次数的周期,时钟刻度:月,默认: 1,范围1-12
* AbpOssManagement.OssObject.MaxUploadFileCount 单次上传文件的数量,未实现 * AbpOssManagement.OssObject.MaxUploadFileCount 单次上传文件的数量,未实现
### 配置定义 ### 配置定义
* Abp.OssManagement.DownloadPackageSize 下载分包大小,分块下载时单次传输的数据大小,未实现 * Abp.OssManagement.DownloadPackageSize 下载分包大小,分块下载时单次传输的数据大小,未实现
* Abp.OssManagement.FileLimitLength 上传文件限制大小,默认:100 * Abp.OssManagement.FileLimitLength 上传文件限制大小,默认:100
* Abp.OssManagement.AllowFileExtensions 允许的上传文件扩展名,多个扩展名以逗号分隔,默认: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 * Abp.OssManagement.AllowFileExtensions 允许的上传文件扩展名,多个扩展名以逗号分隔,默认: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
## 更新日志 ## 更新日志
*【2021-03-10】 变更FileManagement命名空间为OssManagement *【2021-03-10】 变更FileManagement命名空间为OssManagement
*【2021-10-22】 增加PublicFilesController用于身份认证通过的用户上传/下载文件,所有操作限定在用户目录下

675
aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/AppPlatformHttpApiHostModule.cs

@ -1,333 +1,342 @@
using DotNetCore.CAP; using DotNetCore.CAP;
using LINGYUN.Abp.AspNetCore.HttpOverrides; using LINGYUN.Abp.AspNetCore.HttpOverrides;
using LINGYUN.Abp.EventBus.CAP; using LINGYUN.Abp.EventBus.CAP;
using LINGYUN.Abp.ExceptionHandling; using LINGYUN.Abp.ExceptionHandling;
using LINGYUN.Abp.ExceptionHandling.Emailing; using LINGYUN.Abp.ExceptionHandling.Emailing;
using LINGYUN.Abp.Features.LimitValidation.Redis; using LINGYUN.Abp.Features.LimitValidation.Redis;
using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore; using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore;
using LINGYUN.Abp.MultiTenancy.DbFinder; using LINGYUN.Abp.MultiTenancy.DbFinder;
using LINGYUN.Abp.Notifications; using LINGYUN.Abp.Notifications;
using LINGYUN.Abp.OssManagement; using LINGYUN.Abp.OssManagement;
using LINGYUN.Abp.OssManagement.FileSystem; using LINGYUN.Abp.OssManagement.FileSystem;
using LINGYUN.Abp.OssManagement.FileSystem.ImageSharp; using LINGYUN.Abp.OssManagement.FileSystem.ImageSharp;
using LINGYUN.Abp.OssManagement.SettingManagement; using LINGYUN.Abp.OssManagement.SettingManagement;
using LINGYUN.Platform.EntityFrameworkCore; using LINGYUN.Platform.EntityFrameworkCore;
using LINGYUN.Platform.HttpApi; using LINGYUN.Platform.HttpApi;
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.Caching.StackExchangeRedis; using Microsoft.Extensions.Caching.StackExchangeRedis;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;
using StackExchange.Redis; using StackExchange.Redis;
using System; using System;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Text.Encodings.Web; using System.Text.Encodings.Web;
using System.Text.Unicode; using System.Text.Unicode;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.AspNetCore.Authentication.JwtBearer; using Volo.Abp.AspNetCore.Authentication.JwtBearer;
using Volo.Abp.AspNetCore.MultiTenancy; using Volo.Abp.AspNetCore.MultiTenancy;
using Volo.Abp.AspNetCore.Security.Claims; using Volo.Abp.AspNetCore.Security.Claims;
using Volo.Abp.Auditing; using Volo.Abp.Auditing;
using Volo.Abp.AuditLogging.EntityFrameworkCore; using Volo.Abp.AuditLogging.EntityFrameworkCore;
using Volo.Abp.Autofac; using Volo.Abp.Autofac;
using Volo.Abp.BlobStoring; using Volo.Abp.BlobStoring;
using Volo.Abp.BlobStoring.FileSystem; using Volo.Abp.BlobStoring.FileSystem;
using Volo.Abp.Caching; using Volo.Abp.Caching;
using Volo.Abp.Caching.StackExchangeRedis; using Volo.Abp.Caching.StackExchangeRedis;
using Volo.Abp.Data; using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.FeatureManagement.EntityFrameworkCore; using Volo.Abp.FeatureManagement.EntityFrameworkCore;
using Volo.Abp.Http.Client.IdentityModel.Web; using Volo.Abp.Http.Client.IdentityModel.Web;
using Volo.Abp.Identity; using Volo.Abp.Identity;
using Volo.Abp.Json; using Volo.Abp.Json;
using Volo.Abp.Json.SystemTextJson; using Volo.Abp.Json.SystemTextJson;
using Volo.Abp.Localization; using Volo.Abp.Localization;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Volo.Abp.PermissionManagement.EntityFrameworkCore; using Volo.Abp.PermissionManagement.EntityFrameworkCore;
using Volo.Abp.Security.Claims; using Volo.Abp.Security.Claims;
using Volo.Abp.Security.Encryption; using Volo.Abp.Security.Encryption;
using Volo.Abp.SettingManagement.EntityFrameworkCore; using Volo.Abp.SettingManagement.EntityFrameworkCore;
using Volo.Abp.TenantManagement.EntityFrameworkCore; using Volo.Abp.TenantManagement.EntityFrameworkCore;
using Volo.Abp.Threading; using Volo.Abp.Threading;
using Volo.Abp.VirtualFileSystem; using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Platform namespace LINGYUN.Platform
{ {
[DependsOn( [DependsOn(
// typeof(AbpOssManagementAliyunModule), // typeof(AbpOssManagementAliyunModule),
typeof(AbpOssManagementFileSystemModule), // 本地文件系统提供者模块 typeof(AbpOssManagementFileSystemModule), // 本地文件系统提供者模块
typeof(AbpOssManagementFileSystemImageSharpModule), // 本地文件系统图形处理模块 typeof(AbpOssManagementFileSystemImageSharpModule), // 本地文件系统图形处理模块
typeof(AbpOssManagementApplicationModule), typeof(AbpOssManagementApplicationModule),
typeof(AbpOssManagementHttpApiModule), typeof(AbpOssManagementHttpApiModule),
typeof(AbpOssManagementSettingManagementModule), typeof(AbpOssManagementSettingManagementModule),
typeof(PlatformApplicationModule), typeof(PlatformApplicationModule),
typeof(PlatformHttpApiModule), typeof(PlatformHttpApiModule),
typeof(PlatformEntityFrameworkCoreModule), typeof(PlatformEntityFrameworkCoreModule),
typeof(AbpIdentityHttpApiClientModule), typeof(AbpIdentityHttpApiClientModule),
typeof(AbpHttpClientIdentityModelWebModule), typeof(AbpHttpClientIdentityModelWebModule),
typeof(AbpAspNetCoreMultiTenancyModule), typeof(AbpAspNetCoreMultiTenancyModule),
typeof(AbpFeatureManagementEntityFrameworkCoreModule), typeof(AbpFeatureManagementEntityFrameworkCoreModule),
typeof(AbpAuditLoggingEntityFrameworkCoreModule), typeof(AbpAuditLoggingEntityFrameworkCoreModule),
typeof(AbpTenantManagementEntityFrameworkCoreModule), typeof(AbpTenantManagementEntityFrameworkCoreModule),
typeof(AbpSettingManagementEntityFrameworkCoreModule), typeof(AbpSettingManagementEntityFrameworkCoreModule),
typeof(AbpPermissionManagementEntityFrameworkCoreModule), typeof(AbpPermissionManagementEntityFrameworkCoreModule),
typeof(AbpLocalizationManagementEntityFrameworkCoreModule), typeof(AbpLocalizationManagementEntityFrameworkCoreModule),
typeof(AbpAspNetCoreAuthenticationJwtBearerModule), typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(AbpNotificationModule), typeof(AbpNotificationModule),
typeof(AbpEmailingExceptionHandlingModule), typeof(AbpEmailingExceptionHandlingModule),
typeof(AbpCAPEventBusModule), typeof(AbpCAPEventBusModule),
typeof(AbpFeaturesValidationRedisModule), typeof(AbpFeaturesValidationRedisModule),
// typeof(AbpFeaturesClientModule),// 当需要客户端特性限制时取消注释此模块 // typeof(AbpFeaturesClientModule),// 当需要客户端特性限制时取消注释此模块
// typeof(AbpFeaturesValidationRedisClientModule),// 当需要客户端特性限制时取消注释此模块 // typeof(AbpFeaturesValidationRedisClientModule),// 当需要客户端特性限制时取消注释此模块
typeof(AbpDbFinderMultiTenancyModule), typeof(AbpDbFinderMultiTenancyModule),
typeof(AbpCachingStackExchangeRedisModule), typeof(AbpCachingStackExchangeRedisModule),
typeof(AbpAspNetCoreHttpOverridesModule), typeof(AbpAspNetCoreHttpOverridesModule),
typeof(AbpAutofacModule) typeof(AbpAutofacModule)
)] )]
public class AppPlatformHttpApiHostModule : AbpModule public class AppPlatformHttpApiHostModule : AbpModule
{ {
public override void PreConfigureServices(ServiceConfigurationContext context) public override void PreConfigureServices(ServiceConfigurationContext context)
{ {
var configuration = context.Services.GetConfiguration(); var configuration = context.Services.GetConfiguration();
PreConfigure<CapOptions>(options => PreConfigure<CapOptions>(options =>
{ {
options options
.UseMySql(configuration.GetConnectionString("Default")) .UseMySql(configuration.GetConnectionString("Default"))
.UseRabbitMQ(rabbitMQOptions => .UseRabbitMQ(rabbitMQOptions =>
{ {
configuration.GetSection("CAP:RabbitMQ").Bind(rabbitMQOptions); configuration.GetSection("CAP:RabbitMQ").Bind(rabbitMQOptions);
}) })
.UseDashboard(); .UseDashboard();
}); });
} }
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
var hostingEnvironment = context.Services.GetHostingEnvironment(); var hostingEnvironment = context.Services.GetHostingEnvironment();
var configuration = hostingEnvironment.BuildConfiguration(); var configuration = hostingEnvironment.BuildConfiguration();
// 配置Ef // 配置Ef
Configure<AbpDbContextOptions>(options => Configure<AbpDbContextOptions>(options =>
{ {
options.UseMySQL(); options.UseMySQL();
}); });
//// 中文序列化的编码问题 //// 中文序列化的编码问题
Configure<AbpSystemTextJsonSerializerOptions>(options => Configure<AbpSystemTextJsonSerializerOptions>(options =>
{ {
options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All); options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
}); });
Configure<KestrelServerOptions>(options => Configure<KestrelServerOptions>(options =>
{ {
options.Limits.MaxRequestBodySize = null; options.Limits.MaxRequestBodySize = null;
options.Limits.MaxRequestBufferSize = null; options.Limits.MaxRequestBufferSize = null;
}); });
Configure<AbpBlobStoringOptions>(options => Configure<AbpBlobStoringOptions>(options =>
{ {
options.Containers.ConfigureAll((containerName, containerConfiguration) => options.Containers.ConfigureAll((containerName, containerConfiguration) =>
{ {
containerConfiguration.UseFileSystem(fileSystem => containerConfiguration.UseFileSystem(fileSystem =>
{ {
fileSystem.BasePath = Path.Combine(Directory.GetCurrentDirectory(), "file-blob-storing"); fileSystem.BasePath = Path.Combine(Directory.GetCurrentDirectory(), "file-blob-storing");
}); });
}); });
}); });
// 加解密 // 加解密
Configure<AbpStringEncryptionOptions>(options => Configure<AbpStringEncryptionOptions>(options =>
{ {
var encryptionConfiguration = configuration.GetSection("Encryption"); var encryptionConfiguration = configuration.GetSection("Encryption");
if (encryptionConfiguration.Exists()) if (encryptionConfiguration.Exists())
{ {
options.DefaultPassPhrase = encryptionConfiguration["PassPhrase"] ?? options.DefaultPassPhrase; options.DefaultPassPhrase = encryptionConfiguration["PassPhrase"] ?? options.DefaultPassPhrase;
options.DefaultSalt = encryptionConfiguration.GetSection("Salt").Exists() options.DefaultSalt = encryptionConfiguration.GetSection("Salt").Exists()
? Encoding.ASCII.GetBytes(encryptionConfiguration["Salt"]) ? Encoding.ASCII.GetBytes(encryptionConfiguration["Salt"])
: options.DefaultSalt; : options.DefaultSalt;
options.InitVectorBytes = encryptionConfiguration.GetSection("InitVector").Exists() options.InitVectorBytes = encryptionConfiguration.GetSection("InitVector").Exists()
? Encoding.ASCII.GetBytes(encryptionConfiguration["InitVector"]) ? Encoding.ASCII.GetBytes(encryptionConfiguration["InitVector"])
: options.InitVectorBytes; : options.InitVectorBytes;
} }
}); });
// 自定义需要处理的异常 // 自定义需要处理的异常
Configure<AbpExceptionHandlingOptions>(options => Configure<AbpExceptionHandlingOptions>(options =>
{ {
// 加入需要处理的异常类型 // 加入需要处理的异常类型
options.Handlers.Add<Volo.Abp.Data.AbpDbConcurrencyException>(); options.Handlers.Add<Volo.Abp.Data.AbpDbConcurrencyException>();
options.Handlers.Add<AbpInitializationException>(); options.Handlers.Add<AbpInitializationException>();
options.Handlers.Add<ObjectDisposedException>(); options.Handlers.Add<ObjectDisposedException>();
options.Handlers.Add<StackOverflowException>(); options.Handlers.Add<StackOverflowException>();
options.Handlers.Add<OutOfMemoryException>(); options.Handlers.Add<OutOfMemoryException>();
options.Handlers.Add<System.Data.Common.DbException>(); options.Handlers.Add<System.Data.Common.DbException>();
options.Handlers.Add<Microsoft.EntityFrameworkCore.DbUpdateException>(); options.Handlers.Add<Microsoft.EntityFrameworkCore.DbUpdateException>();
options.Handlers.Add<System.Data.DBConcurrencyException>(); options.Handlers.Add<System.Data.DBConcurrencyException>();
}); });
// 自定义需要发送邮件通知的异常类型
Configure<AbpEmailExceptionHandlingOptions>(options => Configure<Volo.Abp.AspNetCore.ExceptionHandling.AbpExceptionHandlingOptions>(options =>
{ {
// 是否发送堆栈信息 // 是否发送错误详情
options.SendStackTrace = true; options.SendExceptionsDetailsToClients = false;
// 未指定异常接收者的默认接收邮件 });
// 指定自己的邮件地址
// options.DefaultReceiveEmail = "colin.in@foxmail.com"; // 自定义需要发送邮件通知的异常类型
}); Configure<AbpEmailExceptionHandlingOptions>(options =>
{
Configure<AbpDistributedCacheOptions>(options => // 是否发送堆栈信息
{ options.SendStackTrace = true;
// 最好统一命名,不然某个缓存变动其他应用服务有例外发生 // 未指定异常接收者的默认接收邮件
options.KeyPrefix = "LINGYUN.Abp.Application"; // 指定自己的邮件地址
// 滑动过期30天 // options.DefaultReceiveEmail = "colin.in@foxmail.com";
options.GlobalCacheEntryOptions.SlidingExpiration = TimeSpan.FromDays(30); });
// 绝对过期60天
options.GlobalCacheEntryOptions.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(60); Configure<AbpDistributedCacheOptions>(options =>
}); {
// 最好统一命名,不然某个缓存变动其他应用服务有例外发生
Configure<RedisCacheOptions>(options => options.KeyPrefix = "LINGYUN.Abp.Application";
{ // 滑动过期30天
var redisConfig = ConfigurationOptions.Parse(options.Configuration); options.GlobalCacheEntryOptions.SlidingExpiration = TimeSpan.FromDays(30);
options.ConfigurationOptions = redisConfig; // 绝对过期60天
options.InstanceName = configuration["Redis:InstanceName"]; options.GlobalCacheEntryOptions.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(60);
}); });
Configure<AbpVirtualFileSystemOptions>(options => Configure<RedisCacheOptions>(options =>
{ {
options.FileSets.AddEmbedded<AppPlatformHttpApiHostModule>("LINGYUN.Platform"); var redisConfig = ConfigurationOptions.Parse(options.Configuration);
}); options.ConfigurationOptions = redisConfig;
options.InstanceName = configuration["Redis:InstanceName"];
// 多租户 });
Configure<AbpMultiTenancyOptions>(options =>
{ Configure<AbpVirtualFileSystemOptions>(options =>
options.IsEnabled = true; {
}); options.FileSets.AddEmbedded<AppPlatformHttpApiHostModule>("LINGYUN.Platform");
});
Configure<AbpAuditingOptions>(options =>
{ // 多租户
options.ApplicationName = "Platform"; Configure<AbpMultiTenancyOptions>(options =>
// 是否启用实体变更记录 {
var entitiesChangedConfig = configuration.GetSection("App:TrackingEntitiesChanged"); options.IsEnabled = true;
if (entitiesChangedConfig.Exists() && entitiesChangedConfig.Get<bool>()) });
{
options Configure<AbpAuditingOptions>(options =>
.EntityHistorySelectors {
.AddAllEntities(); options.ApplicationName = "Platform";
} // 是否启用实体变更记录
}); var entitiesChangedConfig = configuration.GetSection("App:TrackingEntitiesChanged");
if (entitiesChangedConfig.Exists() && entitiesChangedConfig.Get<bool>())
// Swagger {
context.Services.AddSwaggerGen( options
options => .EntityHistorySelectors
{ .AddAllEntities();
options.SwaggerDoc("v1", new OpenApiInfo { Title = "Platform API", Version = "v1" }); }
options.DocInclusionPredicate((docName, description) => true); });
options.CustomSchemaIds(type => type.FullName);
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme // Swagger
{ context.Services.AddSwaggerGen(
Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"", options =>
Name = "Authorization", {
In = ParameterLocation.Header, options.SwaggerDoc("v1", new OpenApiInfo { Title = "Platform API", Version = "v1" });
Scheme = "bearer", options.DocInclusionPredicate((docName, description) => true);
Type = SecuritySchemeType.Http, options.CustomSchemaIds(type => type.FullName);
BearerFormat = "JWT" options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
}); {
options.AddSecurityRequirement(new OpenApiSecurityRequirement Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
{ Name = "Authorization",
{ In = ParameterLocation.Header,
new OpenApiSecurityScheme Scheme = "bearer",
{ Type = SecuritySchemeType.Http,
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } BearerFormat = "JWT"
}, });
new string[] { } options.AddSecurityRequirement(new OpenApiSecurityRequirement
} {
}); {
}); new OpenApiSecurityScheme
{
// 支持本地化语言类型 Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }
Configure<AbpLocalizationOptions>(options => },
{ new string[] { }
options.Languages.Add(new LanguageInfo("en", "en", "English")); }
options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); });
});
options.Resources.AddDynamic();
}); // 支持本地化语言类型
Configure<AbpLocalizationOptions>(options =>
Configure<AbpClaimsMapOptions>(options => {
{ options.Languages.Add(new LanguageInfo("en", "en", "English"));
options.Maps.TryAdd("name", () => AbpClaimTypes.UserName); options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
});
options.Resources.AddDynamic();
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) });
.AddJwtBearer(options =>
{ Configure<AbpClaimsMapOptions>(options =>
options.Authority = configuration["AuthServer:Authority"]; {
options.RequireHttpsMetadata = false; options.Maps.TryAdd("name", () => AbpClaimTypes.UserName);
options.Audience = configuration["AuthServer:ApiName"]; });
});
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
if (!hostingEnvironment.IsDevelopment()) .AddJwtBearer(options =>
{ {
var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]); options.Authority = configuration["AuthServer:Authority"];
context.Services options.RequireHttpsMetadata = false;
.AddDataProtection() options.Audience = configuration["AuthServer:ApiName"];
.PersistKeysToStackExchangeRedis(redis, "Platform-Protection-Keys"); });
}
} if (!hostingEnvironment.IsDevelopment())
{
//public override void OnPostApplicationInitialization(ApplicationInitializationContext context) var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
//{ context.Services
// var backgroundJobManager = context.ServiceProvider.GetRequiredService<IBackgroundJobManager>(); .AddDataProtection()
// // 五分钟执行一次的定时任务 .PersistKeysToStackExchangeRedis(redis, "Platform-Protection-Keys");
// AsyncHelper.RunSync(async () => await }
// backgroundJobManager.EnqueueAsync(CronGenerator.Minute(5), new NotificationCleanupExpritionJobArgs(200))); }
//}
//public override void OnPostApplicationInitialization(ApplicationInitializationContext context)
public override void OnApplicationInitialization(ApplicationInitializationContext context) //{
{ // var backgroundJobManager = context.ServiceProvider.GetRequiredService<IBackgroundJobManager>();
var app = context.GetApplicationBuilder(); // // 五分钟执行一次的定时任务
var env = context.GetEnvironment(); // AsyncHelper.RunSync(async () => await
// http调用链 // backgroundJobManager.EnqueueAsync(CronGenerator.Minute(5), new NotificationCleanupExpritionJobArgs(200)));
app.UseCorrelationId(); //}
// 虚拟文件系统
app.UseStaticFiles(); public override void OnApplicationInitialization(ApplicationInitializationContext context)
// 本地化 {
app.UseAbpRequestLocalization(); var app = context.GetApplicationBuilder();
// 多租户 var env = context.GetEnvironment();
app.UseMultiTenancy(); // http调用链
//路由 app.UseCorrelationId();
app.UseRouting(); // 虚拟文件系统
// 认证 app.UseStaticFiles();
app.UseAuthentication(); // 本地化
// jwt app.UseAbpRequestLocalization();
app.UseJwtTokenMiddleware(); // 多租户
// 授权 app.UseMultiTenancy();
app.UseAuthorization(); //路由
// Swagger app.UseRouting();
app.UseSwagger(); // 认证
// Swagger可视化界面 app.UseAuthentication();
app.UseSwaggerUI(options => // jwt
{ app.UseJwtTokenMiddleware();
options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support Platform API"); // 授权
}); app.UseAuthorization();
// 审计日志 // Swagger
app.UseAuditing(); app.UseSwagger();
// 路由 // Swagger可视化界面
app.UseConfiguredEndpoints(); app.UseSwaggerUI(options =>
{
if (env.IsDevelopment()) options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support Platform API");
{ });
AsyncHelper.RunSync(async () => // 审计日志
await app.ApplicationServices.GetRequiredService<IDataSeeder>() app.UseAuditing();
.SeedAsync()); // 工作单元
} app.UseUnitOfWork();
} // 路由
} app.UseConfiguredEndpoints();
}
if (env.IsDevelopment())
{
AsyncHelper.RunSync(async () =>
await app.ApplicationServices.GetRequiredService<IDataSeeder>()
.SeedAsync());
}
}
}
}

Loading…
Cancel
Save