28 changed files with 1152 additions and 1410 deletions
@ -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>(); |
||||
} |
} |
||||
} |
} |
||||
|
} |
||||
|
|||||
@ -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 |
||||
{ |
{ |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -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); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -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"; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -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); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|||||
@ -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); |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -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}) |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|||||
@ -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}"; |
|
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -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,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"; |
||||
} |
} |
||||
|
} |
||||
|
|||||
@ -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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|||||
@ -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>(); |
||||
} |
} |
||||
|
} |
||||
|
} |
||||
|
|||||
@ -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,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)
|
||||
|
// );
|
||||
|
// });
|
||||
|
//}
|
||||
|
} |
||||
|
} |
||||
|
|||||
@ -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; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,9 +0,0 @@ |
|||||
using System.Threading.Tasks; |
|
||||
|
|
||||
namespace LINGYUN.Abp.OssManagement |
|
||||
{ |
|
||||
public interface IFileValidater |
|
||||
{ |
|
||||
Task ValidationAsync(UploadOssObjectInput input); |
|
||||
} |
|
||||
} |
|
||||
@ -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); |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -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用于身份认证通过的用户上传/下载文件,所有操作限定在用户目录下 |
||||
|
|||||
@ -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…
Reference in new issue