28 changed files with 1152 additions and 1410 deletions
@ -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,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,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); |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue