66 changed files with 3209 additions and 288 deletions
@ -0,0 +1,38 @@ |
|||
namespace Lion.AbpPro.FileManagement.Files; |
|||
|
|||
/// <summary>
|
|||
/// 创建文件
|
|||
/// </summary>
|
|||
public class CreateFileObjectInput |
|||
{ |
|||
/// <summary>
|
|||
/// 文件Provider
|
|||
/// </summary>
|
|||
[Required(ErrorMessage = "文件Provider不能为空")] |
|||
public string ProviderKey { get; set; } |
|||
/// <summary>
|
|||
/// 文件扩展名
|
|||
/// </summary>
|
|||
[Required(ErrorMessage = "文件扩展名不能为空")] |
|||
public string FileExtension { get; set; } |
|||
/// <summary>
|
|||
/// 二进制数据
|
|||
/// </summary>
|
|||
[Required(ErrorMessage = "二进制数据不能为空")] |
|||
public long Bytes { get; set; } |
|||
/// <summary>
|
|||
/// 文件大小
|
|||
/// </summary>
|
|||
[Required(ErrorMessage = "文件大小不能为空")] |
|||
public long FileSize { get; set; } |
|||
/// <summary>
|
|||
/// 文件名称
|
|||
/// </summary>
|
|||
[Required(ErrorMessage = "文件名称不能为空")] |
|||
public string ContentType { get; set; } |
|||
/// <summary>
|
|||
/// 文件名称
|
|||
/// </summary>
|
|||
[Required(ErrorMessage = "文件名称不能为空")] |
|||
public string FileName { get; set; } |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
namespace Lion.AbpPro.FileManagement.Files; |
|||
|
|||
/// <summary>
|
|||
/// 删除文件
|
|||
/// </summary>
|
|||
public class DeleteFileObjectInput |
|||
{ |
|||
/// <summary>
|
|||
/// 文件Id
|
|||
/// </summary>
|
|||
public Guid Id { get; set; } |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
namespace Lion.AbpPro.FileManagement.Files; |
|||
|
|||
public class DownloadFileObjectInput |
|||
{ |
|||
/// <summary>
|
|||
/// 文件Id
|
|||
/// </summary>
|
|||
public Guid Id { get; set; } |
|||
} |
|||
@ -1,8 +0,0 @@ |
|||
namespace Lion.AbpPro.FileManagement.Files.Dto; |
|||
|
|||
public class CreateFileInput |
|||
{ |
|||
[Required(ErrorMessage = "文件名不能为空")] public string FileName { get; set; } |
|||
|
|||
[Required(ErrorMessage = "文件地址不能为空")] public string FilePath { get; set; } |
|||
} |
|||
@ -1,19 +0,0 @@ |
|||
namespace Lion.AbpPro.FileManagement.Files.Dto; |
|||
|
|||
public class FileTokenOutput |
|||
{ |
|||
public string AccessKeyId { get; set; } |
|||
|
|||
public string AccessKeySecret { get; set; } |
|||
|
|||
public string Token { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 过期时间
|
|||
/// </summary>
|
|||
public string Expiration { get; set; } |
|||
|
|||
public string Bucket { get; set; } |
|||
|
|||
public string Region { get; set; } |
|||
} |
|||
@ -1,14 +0,0 @@ |
|||
namespace Lion.AbpPro.FileManagement.Files.Dto; |
|||
|
|||
public class PagingFileOutput |
|||
{ |
|||
public Guid Id { get; set; } |
|||
|
|||
public Guid? TenantId { get; set; } |
|||
|
|||
public string FileName { get; set; } |
|||
|
|||
public string FilePath { get; set; } |
|||
|
|||
public DateTime CreationTime { get; set; } |
|||
} |
|||
@ -1,6 +0,0 @@ |
|||
namespace Lion.AbpPro.FileManagement.Files.Dto; |
|||
|
|||
public class PagingFileInput : PagingBase |
|||
{ |
|||
public string Filter { get; set; } |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
namespace Lion.AbpPro.FileManagement.Files; |
|||
|
|||
public class GetFileObjectInput |
|||
{ |
|||
/// <summary>
|
|||
/// 文件Id
|
|||
/// </summary>
|
|||
public Guid Id { get; set; } |
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
namespace Lion.AbpPro.FileManagement.Files; |
|||
|
|||
public class GetFileObjectOutput |
|||
{ |
|||
/// <summary>
|
|||
/// 文件Id
|
|||
/// </summary>
|
|||
public Guid Id { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 文件Provider
|
|||
/// </summary>
|
|||
public string ProviderKey { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 文件扩展名
|
|||
/// </summary>
|
|||
public string FileExtension { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 二进制数据
|
|||
/// </summary>
|
|||
public byte[] Bytes { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 文件大小
|
|||
/// </summary>
|
|||
public long FileSize { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 文件名称
|
|||
/// </summary>
|
|||
public string ContentType { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 文件名称
|
|||
/// </summary>
|
|||
public string FileName { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 创建时间
|
|||
/// </summary>
|
|||
public DateTime CreationTime { get; set; } |
|||
} |
|||
@ -1,15 +1,34 @@ |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Lion.AbpPro.FileManagement.Files.Dto; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace Lion.AbpPro.FileManagement.Files; |
|||
|
|||
/// <summary>
|
|||
/// 文件
|
|||
/// </summary>
|
|||
public interface IFileAppService : IApplicationService |
|||
{ |
|||
Task<FileTokenOutput> GetFileTokenAsync(); |
|||
Task CreateAsync(CreateFileInput input); |
|||
/// <summary>
|
|||
/// 分页查询文件
|
|||
/// </summary>
|
|||
Task<PagedResultDto<PageFileObjectOutput>> PageAsync(PageFileObjectInput input); |
|||
|
|||
Task<PagedResultDto<PagingFileOutput>> PagingAsync(PagingFileInput input); |
|||
/// <summary>
|
|||
/// 上传文件
|
|||
/// </summary>
|
|||
Task<List<UploadOutput>> UploadAsync(List<IFormFile> files); |
|||
|
|||
/// <summary>
|
|||
/// 删除文件
|
|||
/// </summary>
|
|||
Task DeleteAsync(DeleteFileObjectInput input); |
|||
|
|||
Task<GetFileObjectOutput> GetAsync(GetFileObjectInput input); |
|||
|
|||
/// <summary>
|
|||
/// 下载文件
|
|||
/// </summary>
|
|||
Task<FileContentResult> DownloadAsync(DownloadFileObjectInput input); |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
namespace Lion.AbpPro.FileManagement.Files; |
|||
|
|||
/// <summary>
|
|||
/// 分页查询文件
|
|||
/// </summary>
|
|||
public class PageFileObjectInput : PagingBase |
|||
{ |
|||
/// <summary>
|
|||
/// 开始创建时间
|
|||
/// </summary>
|
|||
public DateTime? StartCreationTime { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 结束创建时间
|
|||
/// </summary>
|
|||
public DateTime? EndCreationTime { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 文件名称
|
|||
/// </summary>
|
|||
public string FileName { get; set; } |
|||
} |
|||
@ -0,0 +1,47 @@ |
|||
namespace Lion.AbpPro.FileManagement.Files; |
|||
|
|||
/// <summary>
|
|||
/// 分页查询文件
|
|||
/// </summary>
|
|||
public class PageFileObjectOutput |
|||
{ |
|||
/// <summary>
|
|||
/// 文件Id
|
|||
/// </summary>
|
|||
public Guid Id { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 文件Provider
|
|||
/// </summary>
|
|||
public string ProviderKey { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 文件扩展名
|
|||
/// </summary>
|
|||
public string FileExtension { get; set; } |
|||
|
|||
// /// <summary>
|
|||
// /// 二进制数据
|
|||
// /// </summary>
|
|||
// public byte[] Bytes { get; set; }
|
|||
|
|||
/// <summary>
|
|||
/// 文件大小
|
|||
/// </summary>
|
|||
public long FileSize { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 文件名称
|
|||
/// </summary>
|
|||
public string ContentType { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 文件名称
|
|||
/// </summary>
|
|||
public string FileName { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 创建时间
|
|||
/// </summary>
|
|||
public DateTime CreationTime { get; set; } |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
namespace Lion.AbpPro.FileManagement.Files; |
|||
|
|||
/// <summary>
|
|||
/// 更新文件
|
|||
/// </summary>
|
|||
public class UpdateFileInput |
|||
{ |
|||
/// <summary>
|
|||
/// 文件Id
|
|||
/// </summary>
|
|||
public Guid Id { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 文件Provider
|
|||
/// </summary>
|
|||
[Required(ErrorMessage = "文件Provider不能为空")] |
|||
public string ProviderKey { get; set; } |
|||
/// <summary>
|
|||
/// 文件扩展名
|
|||
/// </summary>
|
|||
[Required(ErrorMessage = "文件扩展名不能为空")] |
|||
public string FileExtension { get; set; } |
|||
/// <summary>
|
|||
/// 二进制数据
|
|||
/// </summary>
|
|||
[Required(ErrorMessage = "二进制数据不能为空")] |
|||
public long Bytes { get; set; } |
|||
/// <summary>
|
|||
/// 文件大小
|
|||
/// </summary>
|
|||
[Required(ErrorMessage = "文件大小不能为空")] |
|||
public long FileSize { get; set; } |
|||
/// <summary>
|
|||
/// 文件名称
|
|||
/// </summary>
|
|||
[Required(ErrorMessage = "文件名称不能为空")] |
|||
public string ContentType { get; set; } |
|||
/// <summary>
|
|||
/// 文件名称
|
|||
/// </summary>
|
|||
[Required(ErrorMessage = "文件名称不能为空")] |
|||
public string FileName { get; set; } |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
namespace Lion.AbpPro.FileManagement.Files; |
|||
|
|||
public class UploadOutput |
|||
{ |
|||
public Guid Id { get; set; } |
|||
|
|||
public string Name { get; set; } |
|||
|
|||
public bool Success { get; set; } |
|||
|
|||
|
|||
public string Path { get; set; } |
|||
} |
|||
@ -1,9 +1,12 @@ |
|||
using Lion.AbpPro.FileManagement.Files; |
|||
|
|||
namespace Lion.AbpPro.FileManagement; |
|||
|
|||
public class FileManagementApplicationAutoMapperProfile : Profile |
|||
{ |
|||
public FileManagementApplicationAutoMapperProfile() |
|||
{ |
|||
CreateMap<Lion.AbpPro.FileManagement.Files.File, PagingFileOutput>(); |
|||
CreateMap<Files.FileObjectDto, PageFileObjectOutput>(); |
|||
CreateMap<Files.FileObjectDto, GetFileObjectOutput>(); |
|||
} |
|||
} |
|||
@ -1,59 +1,104 @@ |
|||
namespace Lion.AbpPro.FileManagement.Files; |
|||
using Lion.AbpPro.FileManagement.Provider; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.Extensions.Logging; |
|||
|
|||
[Authorize(FileManagementPermissions.FileManagement.Default)] |
|||
public class FileAppService : FileManagementAppService, IFileAppService |
|||
namespace Lion.AbpPro.FileManagement.Files; |
|||
|
|||
/// <summary>
|
|||
/// 文件
|
|||
/// </summary>
|
|||
[Authorize] |
|||
public class FileAppService : ApplicationService, IFileAppService |
|||
{ |
|||
private readonly IFileManager _fileManager; |
|||
private readonly IConfiguration _configuration; |
|||
private readonly FileObjectManager _fileObjectManager; |
|||
private readonly IFileProvider _fileProvider; |
|||
|
|||
public FileAppService(IFileManager fileManager, IConfiguration configuration) |
|||
public FileAppService(FileObjectManager fileObjectManager, IFileProvider fileProvider) |
|||
{ |
|||
_fileManager = fileManager; |
|||
_configuration = configuration; |
|||
_fileObjectManager = fileObjectManager; |
|||
_fileProvider = fileProvider; |
|||
} |
|||
|
|||
public virtual async Task<FileTokenOutput> GetFileTokenAsync() |
|||
/// <summary>
|
|||
/// 分页查询文件
|
|||
/// </summary>
|
|||
public async Task<PagedResultDto<PageFileObjectOutput>> PageAsync(PageFileObjectInput input) |
|||
{ |
|||
// 如何设置 sts https://help.aliyun.com/document_detail/100624.html
|
|||
var regionId = _configuration.GetValue<string>("AliYun:OSS:RegionId"); |
|||
var accessKeyId = _configuration.GetValue<string>("AliYun:OSS:AccessKeyId"); |
|||
var accessKeySecret = _configuration.GetValue<string>("AliYun:OSS:AccessKeySecret"); |
|||
var profile = DefaultProfile.GetProfile(regionId, accessKeyId, accessKeySecret); |
|||
var client = new DefaultAcsClient(profile); |
|||
var request = new AssumeRoleRequest() |
|||
{ |
|||
RoleArn = _configuration.GetValue<string>("AliYun:OSS:RoleArn"), |
|||
RoleSessionName = "Lion.AbpPro" |
|||
}; |
|||
var response = client.GetAcsResponse(request); |
|||
var result = new PagedResultDto<PageFileObjectOutput>(); |
|||
var totalCount = await _fileObjectManager.GetCountAsync(input.FileName, input.StartCreationTime, input.EndCreationTime); |
|||
result.TotalCount = totalCount; |
|||
if (totalCount <= 0) return result; |
|||
var list = await _fileObjectManager.GetListAsync(input.FileName, input.StartCreationTime, input.EndCreationTime, input.PageSize, input.SkipCount); |
|||
result.Items = ObjectMapper.Map<List<FileObjectDto>, List<PageFileObjectOutput>>(list); |
|||
return result; |
|||
} |
|||
|
|||
var result = new FileTokenOutput() |
|||
public async Task<List<UploadOutput>> UploadAsync(List<IFormFile> files) |
|||
{ |
|||
var result = new List<UploadOutput>(); |
|||
foreach (var formFile in files) |
|||
{ |
|||
AccessKeyId = response.Credentials.AccessKeyId, |
|||
AccessKeySecret = response.Credentials.AccessKeySecret, |
|||
Token = response.Credentials.SecurityToken, |
|||
Expiration = response.Credentials.Expiration, |
|||
Region = _configuration.GetValue<string>("AliYun:OSS:RegionId"), |
|||
Bucket = _configuration.GetValue<string>("AliYun:OSS:ContainerName"), |
|||
}; |
|||
return await Task.FromResult(result); |
|||
try |
|||
{ |
|||
var item = new UploadOutput(); |
|||
// 获取文件的二进制数据
|
|||
using var memoryStream = new MemoryStream(); |
|||
await formFile.CopyToAsync(memoryStream); |
|||
var fileBytes = memoryStream.ToArray(); |
|||
|
|||
// 这里可以对 fileBytes 进行后续处理,例如保存到数据库或文件系统等
|
|||
// 示例:将文件保存到数据库
|
|||
var updateResult = await _fileProvider.UploadAsync(new UpdateDto() |
|||
{ |
|||
FileName = formFile.FileName, |
|||
Bytes = fileBytes, |
|||
ContentType = formFile.ContentType, |
|||
FileSize = formFile.Length |
|||
}); |
|||
|
|||
result.Add(new UploadOutput() |
|||
{ |
|||
Id = updateResult.Id, |
|||
Name = updateResult.FileName, |
|||
Path = updateResult.FilePath, |
|||
Success = true |
|||
}); |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
Logger.LogError(e, "上传文件失败"); |
|||
result.Add(new UploadOutput() |
|||
{ |
|||
Id = Guid.Empty, |
|||
Name = formFile.FileName, |
|||
Path = string.Empty, |
|||
Success = false |
|||
}); |
|||
} |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
[Authorize(FileManagementPermissions.FileManagement.Upload)] |
|||
public virtual async Task CreateAsync(CreateFileInput input) |
|||
|
|||
/// <summary>
|
|||
/// 删除文件
|
|||
/// </summary>
|
|||
public Task DeleteAsync(DeleteFileObjectInput input) |
|||
{ |
|||
await _fileManager.CreateAsync(input.FileName, input.FilePath); |
|||
return _fileObjectManager.DeleteAsync(input.Id); |
|||
} |
|||
|
|||
public virtual async Task<PagedResultDto<PagingFileOutput>> PagingAsync(PagingFileInput input) |
|||
public async Task<GetFileObjectOutput> GetAsync(GetFileObjectInput input) |
|||
{ |
|||
var result = new PagedResultDto<PagingFileOutput>(); |
|||
var totalCount = await _fileManager.CountAsync(input.Filter); |
|||
result.TotalCount = totalCount; |
|||
if (totalCount <= 0) return result; |
|||
var entities = await _fileManager.PagingAsync(input.Filter, input.PageSize, |
|||
input.SkipCount); |
|||
result.Items = ObjectMapper.Map<List<File>, List<PagingFileOutput>>(entities); |
|||
return result; |
|||
var file = await _fileObjectManager.GetAsync(input.Id); |
|||
return ObjectMapper.Map<FileObjectDto, GetFileObjectOutput>(file); |
|||
} |
|||
|
|||
public async Task<FileContentResult> DownloadAsync(DownloadFileObjectInput input) |
|||
{ |
|||
var file = await _fileObjectManager.GetAsync(input.Id); |
|||
return new Microsoft.AspNetCore.Mvc.FileContentResult(file.Bytes, file.ContentType); |
|||
} |
|||
} |
|||
@ -0,0 +1,51 @@ |
|||
namespace Lion.AbpPro.FileManagement.Files; |
|||
|
|||
/// <summary>
|
|||
/// 文件
|
|||
/// </summary>
|
|||
public class FileObjectDto |
|||
{ |
|||
/// <summary>
|
|||
/// 主键Id
|
|||
/// </summary>
|
|||
public Guid Id { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 创建时间
|
|||
/// </summary>
|
|||
public DateTime CreationTime { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 文件Provider
|
|||
/// </summary>
|
|||
public string ProviderKey { get; set; } |
|||
/// <summary>
|
|||
/// 文件扩展名
|
|||
/// </summary>
|
|||
public string FileExtension { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 二进制数据
|
|||
/// </summary>
|
|||
public byte[] Bytes { get; set; } |
|||
/// <summary>
|
|||
/// 文件大小
|
|||
/// </summary>
|
|||
public long FileSize { get; set; } |
|||
/// <summary>
|
|||
/// 文件名称
|
|||
/// </summary>
|
|||
public string ContentType { get; set; } |
|||
/// <summary>
|
|||
/// 文件名称
|
|||
/// </summary>
|
|||
public string FileName { get; set; } |
|||
|
|||
|
|||
private const string CacheKeyFormat = "i:{0}"; |
|||
|
|||
public static string CalculateCacheKey(Guid id) |
|||
{ |
|||
return string.Format(CacheKeyFormat, id); |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
namespace Lion.AbpPro.FileManagement.Provider; |
|||
|
|||
public class UpdateDto |
|||
{ |
|||
/// <summary>
|
|||
/// 二进制数据
|
|||
/// </summary>
|
|||
public byte[] Bytes { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 文件大小
|
|||
/// </summary>
|
|||
public long FileSize { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 文件名称
|
|||
/// </summary>
|
|||
public string ContentType { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 文件名称
|
|||
/// </summary>
|
|||
public string FileName { get; set; } |
|||
|
|||
public Dictionary<string, object> ExtraProperties { get; set; } |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
namespace Lion.AbpPro.FileManagement.Provider; |
|||
|
|||
public class UpdateResult |
|||
{ |
|||
public Guid Id { get; set; } |
|||
|
|||
public string FileName { get; set; } |
|||
|
|||
public string FilePath { get; set; } |
|||
|
|||
public UpdateResult() |
|||
{ |
|||
ExtraProperties = new Dictionary<string, object>(); |
|||
} |
|||
|
|||
public Dictionary<string, object> ExtraProperties { get; set; } |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using AutoMapper; |
|||
using Lion.AbpPro.FileManagement.Files; |
|||
|
|||
namespace Lion.AbpPro.FileManagement |
|||
{ |
|||
public class FileManagementDomainAutoMapperProfile : Profile |
|||
{ |
|||
public FileManagementDomainAutoMapperProfile() |
|||
{ |
|||
CreateMap<FileObject, FileObjectDto>(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,9 +1,16 @@ |
|||
using Volo.Abp.AutoMapper; |
|||
|
|||
namespace Lion.AbpPro.FileManagement; |
|||
|
|||
[DependsOn( |
|||
typeof(AbpDddDomainModule), |
|||
typeof(AbpAutoMapperModule), |
|||
typeof(FileManagementDomainSharedModule) |
|||
)] |
|||
public class FileManagementDomainModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpAutoMapperOptions>(options => { options.AddMaps<FileManagementDomainModule>(); }); |
|||
} |
|||
} |
|||
@ -1,22 +0,0 @@ |
|||
namespace Lion.AbpPro.FileManagement.Files; |
|||
|
|||
public class File: FullAuditedAggregateRoot<Guid>, IMultiTenant |
|||
{ |
|||
public Guid? TenantId { get; private set; } |
|||
|
|||
public string FileName { get; private set; } |
|||
|
|||
public string FilePath { get; private set; } |
|||
|
|||
private File() |
|||
{ |
|||
|
|||
} |
|||
|
|||
public File(Guid id, Guid? tenantId, string fileName, string filePath) : base(id) |
|||
{ |
|||
TenantId = tenantId; |
|||
FileName = fileName; |
|||
FilePath = filePath; |
|||
} |
|||
} |
|||
@ -1,33 +0,0 @@ |
|||
namespace Lion.AbpPro.FileManagement.Files; |
|||
|
|||
public class FileManager : DomainService, IFileManager |
|||
{ |
|||
private readonly IFileRepository _fileRepository; |
|||
|
|||
public FileManager(IFileRepository fileRepository) |
|||
{ |
|||
_fileRepository = fileRepository; |
|||
} |
|||
|
|||
public virtual async Task CreateAsync(string fileName, string filePath) |
|||
{ |
|||
Check.NotNullOrWhiteSpace(fileName, nameof(fileName)); |
|||
Check.NotNullOrWhiteSpace(filePath, nameof(filePath)); |
|||
var entity = new File(GuidGenerator.Create(), CurrentTenant.Id, fileName, filePath); |
|||
await _fileRepository.InsertAsync(entity); |
|||
} |
|||
|
|||
public virtual async Task<List<File>> PagingAsync( |
|||
string filter = null, |
|||
int maxResultCount = 10, |
|||
int skipCount = 0) |
|||
{ |
|||
return await _fileRepository.GetPagingListAsync(filter, maxResultCount, skipCount); |
|||
} |
|||
|
|||
|
|||
public virtual async Task<long> CountAsync(string filter = null) |
|||
{ |
|||
return await _fileRepository.GetPagingCountAsync(filter); |
|||
} |
|||
} |
|||
@ -0,0 +1,137 @@ |
|||
using Lion.AbpPro.Core; |
|||
|
|||
namespace Lion.AbpPro.FileManagement.Files; |
|||
|
|||
/// <summary>
|
|||
/// 文件
|
|||
/// </summary>
|
|||
public class FileObject : FullAuditedAggregateRoot<Guid>, IMultiTenant |
|||
{ |
|||
|
|||
|
|||
public FileObject( |
|||
Guid id, |
|||
string providerKey, |
|||
byte[] bytes, |
|||
long fileSize, |
|||
string contentType, |
|||
string fileName, |
|||
Guid? tenantId = null |
|||
) : base(id) |
|||
{ |
|||
SetProviderKey(providerKey); |
|||
SetBytes(bytes); |
|||
SetFileSize(fileSize); |
|||
SetContentType(contentType); |
|||
SetFileName(fileName); |
|||
TenantId = tenantId; |
|||
} |
|||
|
|||
public Guid? TenantId { get; private set; } |
|||
|
|||
/// <summary>
|
|||
/// 文件名称
|
|||
/// </summary>
|
|||
public string FileName { get; private set; } |
|||
|
|||
/// <summary>
|
|||
/// 文件名称
|
|||
/// </summary>
|
|||
public string ContentType { get; private set; } |
|||
|
|||
|
|||
/// <summary>
|
|||
/// 文件大小
|
|||
/// </summary>
|
|||
public long FileSize { get; private set; } |
|||
|
|||
|
|||
/// <summary>
|
|||
/// 文件扩展名
|
|||
/// </summary>
|
|||
public string FileExtension { get; private set; } |
|||
|
|||
/// <summary>
|
|||
/// 二进制数据
|
|||
/// </summary>
|
|||
public byte[] Bytes { get; private set; } |
|||
|
|||
/// <summary>
|
|||
/// 文件Provider
|
|||
/// </summary>
|
|||
public string ProviderKey { get; private set; } |
|||
|
|||
|
|||
/// <summary>
|
|||
/// 设置文件Provider
|
|||
/// </summary>
|
|||
private void SetProviderKey(string providerKey) |
|||
{ |
|||
Guard.NotNullOrWhiteSpace(providerKey, nameof(providerKey), 128, 0); |
|||
ProviderKey = providerKey; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 设置文件扩展名
|
|||
/// </summary>
|
|||
private void SetFileExtension(string fileExtension) |
|||
{ |
|||
Guard.NotNullOrWhiteSpace(fileExtension, nameof(fileExtension), 36, 0); |
|||
FileExtension = fileExtension; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 设置二进制数据
|
|||
/// </summary>
|
|||
private void SetBytes(byte[] bytes) |
|||
{ |
|||
Bytes = bytes; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 设置文件大小
|
|||
/// </summary>
|
|||
private void SetFileSize(long fileSize) |
|||
{ |
|||
FileSize = fileSize; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 设置文件名称
|
|||
/// </summary>
|
|||
private void SetContentType(string contentType) |
|||
{ |
|||
Guard.NotNullOrWhiteSpace(contentType, nameof(contentType), 128, 0); |
|||
ContentType = contentType; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 设置文件名称
|
|||
/// </summary>
|
|||
private void SetFileName(string fileName) |
|||
{ |
|||
Guard.NotNullOrWhiteSpace(fileName, nameof(fileName), 128, 0); |
|||
SetFileExtension(Path.GetExtension(fileName)); |
|||
FileName = fileName; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 更新文件
|
|||
/// </summary>
|
|||
public void Update( |
|||
string providerKey, |
|||
string fileExtension, |
|||
byte[] bytes, |
|||
long fileSize, |
|||
string contentType, |
|||
string fileName |
|||
) |
|||
{ |
|||
SetProviderKey(providerKey); |
|||
SetFileExtension(fileExtension); |
|||
SetBytes(bytes); |
|||
SetFileSize(fileSize); |
|||
SetContentType(contentType); |
|||
SetFileName(fileName); |
|||
} |
|||
} |
|||
@ -0,0 +1,65 @@ |
|||
using Volo.Abp.ObjectMapping; |
|||
|
|||
namespace Lion.AbpPro.FileManagement.Files; |
|||
|
|||
public class FileObjectManager : DomainService |
|||
{ |
|||
private readonly IFileObjectRepository _fileObjectRepository; |
|||
private readonly IObjectMapper _objectMapper; |
|||
private readonly ICurrentTenant _currentTenant; |
|||
|
|||
public FileObjectManager(IFileObjectRepository iIFileObjectRepository, IObjectMapper objectMapper, ICurrentTenant currentTenant) |
|||
{ |
|||
_fileObjectRepository = iIFileObjectRepository; |
|||
_objectMapper = objectMapper; |
|||
_currentTenant = currentTenant; |
|||
} |
|||
|
|||
public async Task<List<FileObjectDto>> GetListAsync(string fileName, DateTime? startDateTime = null, DateTime? endDateTime = null, int maxResultCount = 10, int skipCount = 0) |
|||
{ |
|||
return await _fileObjectRepository.GetListAsync(fileName, startDateTime, endDateTime, maxResultCount, skipCount); |
|||
} |
|||
|
|||
public async Task<long> GetCountAsync(string fileName, DateTime? startDateTime = null, DateTime? endDateTime = null) |
|||
{ |
|||
return await _fileObjectRepository.GetCountAsync(fileName, startDateTime, endDateTime); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 创建文件
|
|||
/// </summary>
|
|||
public async Task<FileObjectDto> CreateAsync( |
|||
Guid id, |
|||
string fileName, |
|||
byte[] bytes, |
|||
long fileSize, |
|||
string contentType, |
|||
string providerKey |
|||
) |
|||
{ |
|||
var entity = new FileObject(id, providerKey, bytes, fileSize, contentType, fileName, _currentTenant.Id); |
|||
entity = await _fileObjectRepository.InsertAsync(entity); |
|||
return _objectMapper.Map<FileObject, FileObjectDto>(entity); |
|||
} |
|||
|
|||
|
|||
/// <summary>
|
|||
/// 删除文件
|
|||
/// </summary>
|
|||
public async Task DeleteAsync(Guid id) |
|||
{ |
|||
var entity = await _fileObjectRepository.FindAsync(id); |
|||
if (entity == null) throw new UserFriendlyException($"文件不存在"); |
|||
await _fileObjectRepository.DeleteAsync(entity); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 删除文件
|
|||
/// </summary>
|
|||
public async Task<FileObjectDto> GetAsync(Guid id) |
|||
{ |
|||
var entity = await _fileObjectRepository.FindAsync(id); |
|||
if (entity == null) throw new UserFriendlyException($"文件不存在"); |
|||
return _objectMapper.Map<FileObject, FileObjectDto>(entity); |
|||
} |
|||
} |
|||
@ -1,15 +0,0 @@ |
|||
namespace Lion.AbpPro.FileManagement.Files; |
|||
|
|||
public interface IFileManager |
|||
{ |
|||
Task CreateAsync(string fileName, string filePath); |
|||
|
|||
Task<List<File>> PagingAsync( |
|||
string filter = null, |
|||
int maxResultCount = 10, |
|||
int skipCount = 0); |
|||
|
|||
Task<long> CountAsync(string filter = null); |
|||
IAbpLazyServiceProvider LazyServiceProvider { get; set; } |
|||
IServiceProvider ServiceProvider { get; set; } |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
namespace Lion.AbpPro.FileManagement.Files; |
|||
|
|||
public interface IFileObjectRepository : IBasicRepository<FileObject, Guid> |
|||
{ |
|||
Task<List<FileObjectDto>> GetListAsync(string fileName, DateTime? startDateTime = null, DateTime? endDateTime = null, int maxResultCount = 10, int skipCount = 0); |
|||
|
|||
Task<long> GetCountAsync(string fileName, DateTime? startDateTime = null, DateTime? endDateTime = null); |
|||
} |
|||
@ -1,13 +0,0 @@ |
|||
namespace Lion.AbpPro.FileManagement.Files; |
|||
|
|||
public interface IFileRepository: IRepository<File, Guid> |
|||
{ |
|||
Task<List<File>> GetPagingListAsync( |
|||
string filter = null, |
|||
int maxResultCount = 10, |
|||
int skipCount = 0, |
|||
CancellationToken cancellationToken = default); |
|||
|
|||
Task<long> GetPagingCountAsync(string filter = null, |
|||
CancellationToken cancellationToken = default); |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
using Lion.AbpPro.FileManagement.Files; |
|||
using Volo.Abp.Guids; |
|||
|
|||
namespace Lion.AbpPro.FileManagement.Provider; |
|||
|
|||
public class DatabaseFileProvider : IFileProvider, ITransientDependency |
|||
{ |
|||
public const string Name = nameof(DatabaseFileProvider); |
|||
private readonly FileObjectManager _fileObjectManager; |
|||
private readonly IGuidGenerator _guidGenerator; |
|||
|
|||
public DatabaseFileProvider(FileObjectManager fileObjectManager, IGuidGenerator guidGenerator) |
|||
{ |
|||
_fileObjectManager = fileObjectManager; |
|||
_guidGenerator = guidGenerator; |
|||
} |
|||
|
|||
public async Task<UpdateResult> UploadAsync(UpdateDto input) |
|||
{ |
|||
var id = _guidGenerator.Create(); |
|||
var fileName = id + "_" + input.FileName; |
|||
await _fileObjectManager.CreateAsync(id, fileName, input.Bytes, input.FileSize, input.ContentType, Name); |
|||
return new UpdateResult() |
|||
{ |
|||
Id = id, |
|||
FileName = fileName, |
|||
FilePath = fileName |
|||
}; |
|||
} |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
namespace Lion.AbpPro.FileManagement.Provider; |
|||
|
|||
public interface IFileProvider |
|||
{ |
|||
Task<UpdateResult> UploadAsync(UpdateDto input); |
|||
} |
|||
@ -0,0 +1,49 @@ |
|||
using System.Linq.Dynamic.Core; |
|||
using Volo.Abp.Domain.Repositories.EntityFrameworkCore; |
|||
using Volo.Abp.EntityFrameworkCore; |
|||
using Microsoft.EntityFrameworkCore; |
|||
|
|||
namespace Lion.AbpPro.FileManagement.EntityFrameworkCore.Files; |
|||
|
|||
/// <summary>
|
|||
/// 文件 仓储Ef core 实现
|
|||
/// </summary>
|
|||
public class EfCoreFileObjectRepository : |
|||
EfCoreRepository<FileManagementDbContext, FileObject, Guid>, |
|||
IFileObjectRepository |
|||
{ |
|||
public EfCoreFileObjectRepository(IDbContextProvider<FileManagementDbContext> dbContextProvider) : base(dbContextProvider) |
|||
{ |
|||
} |
|||
|
|||
public async Task<List<FileObjectDto>> GetListAsync(string fileName, DateTime? startDateTime = null, DateTime? endDateTime = null,int maxResultCount = 10, int skipCount = 0) |
|||
{ |
|||
return await (await GetDbSetAsync()) |
|||
.WhereIf(fileName.IsNotNullOrWhiteSpace(),e=>e.FileName.Contains(fileName)) |
|||
.WhereIf(startDateTime.HasValue, e => e.CreationTime >= startDateTime.Value) |
|||
.WhereIf(endDateTime.HasValue, e => e.CreationTime <= endDateTime.Value) |
|||
.OrderByDescending(e => e.CreationTime) |
|||
.PageBy(skipCount, maxResultCount) |
|||
.Select(e => new FileObjectDto |
|||
{ |
|||
|
|||
Id = e.Id, |
|||
CreationTime = e.CreationTime, |
|||
FileName = e.FileName, |
|||
FileSize = e.FileSize, |
|||
FileExtension = e.FileExtension, |
|||
ContentType = e.ContentType, |
|||
ProviderKey = e.ProviderKey |
|||
}) // 选择指定字段
|
|||
.ToListAsync(); |
|||
} |
|||
|
|||
public async Task<long> GetCountAsync(string fileName, DateTime? startDateTime = null, DateTime? endDateTime = null) |
|||
{ |
|||
return await (await GetDbSetAsync()) |
|||
.WhereIf(fileName.IsNotNullOrWhiteSpace(),e=>e.FileName.Contains(fileName)) |
|||
.WhereIf(startDateTime.HasValue, e => e.CreationTime >= startDateTime.Value) |
|||
.WhereIf(endDateTime.HasValue, e => e.CreationTime <= endDateTime.Value) |
|||
.CountAsync(); |
|||
} |
|||
} |
|||
@ -1,31 +0,0 @@ |
|||
namespace Lion.AbpPro.FileManagement.EntityFrameworkCore.Files; |
|||
|
|||
public class EfCoreFileRepository: EfCoreRepository<IFileManagementDbContext,Lion.AbpPro.FileManagement.Files.File, Guid>, IFileRepository |
|||
{ |
|||
public EfCoreFileRepository(IDbContextProvider<IFileManagementDbContext> dbContextProvider) : base(dbContextProvider) |
|||
{ |
|||
} |
|||
|
|||
public async Task<List<Lion.AbpPro.FileManagement.Files.File>> GetPagingListAsync( |
|||
string filter = null, |
|||
int maxResultCount = 10, |
|||
int skipCount = 0, |
|||
CancellationToken cancellationToken = default) |
|||
{ |
|||
return await (await GetDbSetAsync()) |
|||
.WhereIf(!filter.IsNullOrWhiteSpace(), |
|||
e => (e.FileName.Contains(filter))) |
|||
.OrderByDescending(e => e.CreationTime) |
|||
.PageBy(skipCount, maxResultCount) |
|||
.ToListAsync(GetCancellationToken(cancellationToken)); |
|||
} |
|||
|
|||
public async Task<long> GetPagingCountAsync(string filter = null, |
|||
CancellationToken cancellationToken = default) |
|||
{ |
|||
return await (await GetDbSetAsync()) |
|||
.WhereIf(!filter.IsNullOrWhiteSpace(), |
|||
e => (e.FileName.Contains(filter))) |
|||
.CountAsync(cancellationToken: cancellationToken); |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,61 @@ |
|||
using System; |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
|
|||
#nullable disable |
|||
|
|||
namespace Lion.AbpPro.Migrations |
|||
{ |
|||
/// <inheritdoc />
|
|||
public partial class _102 : Migration |
|||
{ |
|||
/// <inheritdoc />
|
|||
protected override void Up(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.CreateTable( |
|||
name: "AbpFileObjects", |
|||
columns: table => new |
|||
{ |
|||
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"), |
|||
TenantId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"), |
|||
FileName = table.Column<string>(type: "varchar(128)", maxLength: 128, nullable: false, comment: "文件名称") |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
ContentType = table.Column<string>(type: "varchar(128)", maxLength: 128, nullable: false, comment: "文件名称") |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
FileSize = table.Column<long>(type: "bigint", nullable: false, comment: "文件大小"), |
|||
FileExtension = table.Column<string>(type: "varchar(36)", maxLength: 36, nullable: false, comment: "文件扩展名") |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
Bytes = table.Column<byte[]>(type: "longblob", nullable: true, comment: "二进制数据"), |
|||
ProviderKey = table.Column<string>(type: "varchar(128)", maxLength: 128, nullable: false, comment: "文件Provider") |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
ExtraProperties = table.Column<string>(type: "longtext", nullable: false) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
ConcurrencyStamp = table.Column<string>(type: "varchar(40)", maxLength: 40, nullable: false) |
|||
.Annotation("MySql:CharSet", "utf8mb4"), |
|||
CreationTime = table.Column<DateTime>(type: "datetime(6)", nullable: false), |
|||
CreatorId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"), |
|||
LastModificationTime = table.Column<DateTime>(type: "datetime(6)", nullable: true), |
|||
LastModifierId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"), |
|||
IsDeleted = table.Column<bool>(type: "tinyint(1)", nullable: false, defaultValue: false), |
|||
DeleterId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"), |
|||
DeletionTime = table.Column<DateTime>(type: "datetime(6)", nullable: true) |
|||
}, |
|||
constraints: table => |
|||
{ |
|||
table.PrimaryKey("PK_AbpFileObjects", x => x.Id); |
|||
}) |
|||
.Annotation("MySql:CharSet", "utf8mb4"); |
|||
|
|||
migrationBuilder.CreateIndex( |
|||
name: "IX_AbpFileObjects_FileName", |
|||
table: "AbpFileObjects", |
|||
column: "FileName"); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
protected override void Down(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.DropTable( |
|||
name: "AbpFileObjects"); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue