40 changed files with 1301 additions and 5 deletions
@ -0,0 +1,16 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.Ddd.Application" Version="3.0.0" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\LINGYUN.Abp.FileManagement.Domain.Shared\LINGYUN.Abp.FileManagement.Domain.Shared.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,11 @@ |
|||
using Volo.Abp.Application; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace LINGYUN.Abp.FileManagement |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpDddApplicationModule))] |
|||
public class AbpFileManagementApplicationContractsModule : AbpModule |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace LINGYUN.Abp.FileManagement |
|||
{ |
|||
public class FileCopyOrMoveDto |
|||
{ |
|||
[Required] |
|||
[StringLength(255)] |
|||
public string Path { get; set; } |
|||
|
|||
[Required] |
|||
[StringLength(255)] |
|||
public string Name { get; set; } |
|||
|
|||
[Required] |
|||
[StringLength(255)] |
|||
public string ToPath { get; set; } |
|||
|
|||
[StringLength(255)] |
|||
public string ToName { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Volo.Abp.Auditing; |
|||
|
|||
namespace LINGYUN.Abp.FileManagement |
|||
{ |
|||
public class FileCreateDto |
|||
{ |
|||
/// <summary>
|
|||
/// 文件名
|
|||
/// </summary>
|
|||
[Required] |
|||
[StringLength(255)] |
|||
public string Name { get; set; } |
|||
/// <summary>
|
|||
/// 文件路径
|
|||
/// </summary>
|
|||
[StringLength(255)] |
|||
public string Path { get; set; } |
|||
/// <summary>
|
|||
/// 文件数据,前端无需传递此参数,由控制器传递
|
|||
/// </summary>
|
|||
[DisableAuditing] |
|||
public byte[] Data { get; set; } |
|||
/// <summary>
|
|||
/// 当前字节数
|
|||
/// </summary>
|
|||
[Required] |
|||
public int CurrentByte { get; set; } |
|||
/// <summary>
|
|||
/// 最大字节数
|
|||
/// </summary>
|
|||
[Required] |
|||
public int TotalByte { get; set; } |
|||
/// <summary>
|
|||
/// 是否覆盖文件
|
|||
/// </summary>
|
|||
public bool Rewrite { get; set; } = false; |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace LINGYUN.Abp.FileManagement |
|||
{ |
|||
public class FileDeleteDto |
|||
{ |
|||
[Required] |
|||
[StringLength(255)] |
|||
public string Path { get; set; } |
|||
|
|||
[Required] |
|||
[StringLength(255)] |
|||
public string Name { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
using System; |
|||
|
|||
namespace LINGYUN.Abp.FileManagement |
|||
{ |
|||
public class FileSystemDto |
|||
{ |
|||
public FileSystemType Type { get; set; } |
|||
public string Name { get; set; } |
|||
public string Parent { get; set; } |
|||
public long? Size { get; set; } |
|||
public DateTime CreationTime { get; set; } |
|||
public DateTime? LastModificationTime { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace LINGYUN.Abp.FileManagement |
|||
{ |
|||
public class FileSystemGetDto |
|||
{ |
|||
[Required] |
|||
[StringLength(255)] |
|||
public string Path { get; set; } |
|||
|
|||
[Required] |
|||
[StringLength(255)] |
|||
public string Name { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
namespace LINGYUN.Abp.FileManagement |
|||
{ |
|||
public enum FileSystemType |
|||
{ |
|||
Folder = 0, |
|||
File = 1 |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace LINGYUN.Abp.FileManagement |
|||
{ |
|||
public class FileSystemUpdateDto |
|||
{ |
|||
[Required] |
|||
[StringLength(255)] |
|||
public string NewName { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace LINGYUN.Abp.FileManagement |
|||
{ |
|||
public class FolderCopyDto |
|||
{ |
|||
[Required] |
|||
[StringLength(255)] |
|||
public string CopyToPath { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace LINGYUN.Abp.FileManagement |
|||
{ |
|||
public class FolderCreateDto |
|||
{ |
|||
[Required] |
|||
[StringLength(255)] |
|||
public string Path { get; set; } |
|||
|
|||
public string Parent { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace LINGYUN.Abp.FileManagement |
|||
{ |
|||
public class FolderMoveDto |
|||
{ |
|||
[Required] |
|||
[StringLength(255)] |
|||
public string MoveToPath { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace LINGYUN.Abp.FileManagement |
|||
{ |
|||
public class GetFileSystemListDto : PagedAndSortedResultRequestDto |
|||
{ |
|||
// TODO: Windows最大路径长度,超过了貌似也无效了吧
|
|||
[StringLength(255)] |
|||
public string Parent { get; set; } |
|||
|
|||
public string Filter { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
using System.IO; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace LINGYUN.Abp.FileManagement |
|||
{ |
|||
public interface IFileSystemAppService : IApplicationService |
|||
{ |
|||
Task<FileSystemDto> GetAsync(FileSystemGetDto input); |
|||
|
|||
Task<PagedResultDto<FileSystemDto>> GetListAsync(GetFileSystemListDto input); |
|||
|
|||
Task CreateFolderAsync(FolderCreateDto input); |
|||
|
|||
Task<FileSystemDto> UpdateAsync([Required, StringLength(255)] string name, FileSystemUpdateDto input); |
|||
|
|||
Task DeleteFolderAsync([Required, StringLength(255)] string path); |
|||
|
|||
Task MoveFolderAsync([Required, StringLength(255)] string path, FolderMoveDto input); |
|||
|
|||
Task CopyFolderAsync([Required, StringLength(255)] string path, FolderCopyDto input); |
|||
|
|||
Task CreateFileAsync(FileCreateDto input); |
|||
|
|||
Task DeleteFileAsync(FileDeleteDto input); |
|||
|
|||
Task MoveFileAsync(FileCopyOrMoveDto input); |
|||
|
|||
Task CopyFileAsync(FileCopyOrMoveDto input); |
|||
|
|||
Task<Stream> DownloadFileAsync(FileSystemGetDto input); |
|||
} |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
using LINGYUN.Abp.FileManagement.Localization; |
|||
using Volo.Abp.Authorization.Permissions; |
|||
using Volo.Abp.Localization; |
|||
|
|||
namespace LINGYUN.Abp.FileManagement.Permissions |
|||
{ |
|||
public class AbpFileManagementPermissionDefinitionProvider : PermissionDefinitionProvider |
|||
{ |
|||
public override void Define(IPermissionDefinitionContext context) |
|||
{ |
|||
var fileManagement = context.AddGroup(AbpFileManagementPermissions.GroupName, L("Permission:FileManagement")); |
|||
|
|||
var fileSystem = fileManagement.AddPermission(AbpFileManagementPermissions.FileSystem.Default, L("Permission:FileSystem")); |
|||
fileSystem.AddChild(AbpFileManagementPermissions.FileSystem.Create, L("Permission:CreateFolder")); |
|||
fileSystem.AddChild(AbpFileManagementPermissions.FileSystem.Delete, L("Permission:DeleteFolder")); |
|||
fileSystem.AddChild(AbpFileManagementPermissions.FileSystem.Update, L("Permission:UpdateFolder")); |
|||
fileSystem.AddChild(AbpFileManagementPermissions.FileSystem.Copy, L("Permission:CopyFolder")); |
|||
fileSystem.AddChild(AbpFileManagementPermissions.FileSystem.Move, L("Permission:MoveFolder")); |
|||
|
|||
var fileManager = fileSystem.AddChild(AbpFileManagementPermissions.FileSystem.FileManager.Default, L("Permission:FileManager")); |
|||
fileManager.AddChild(AbpFileManagementPermissions.FileSystem.FileManager.Create, L("Permission:AppendFile")); |
|||
fileManager.AddChild(AbpFileManagementPermissions.FileSystem.FileManager.Update, L("Permission:UpdateFile")); |
|||
fileManager.AddChild(AbpFileManagementPermissions.FileSystem.FileManager.Delete, L("Permission:DeleteFile")); |
|||
fileManager.AddChild(AbpFileManagementPermissions.FileSystem.FileManager.Copy, L("Permission:CopyFile")); |
|||
fileManager.AddChild(AbpFileManagementPermissions.FileSystem.FileManager.Move, L("Permission:MoveFile")); |
|||
fileManager.AddChild(AbpFileManagementPermissions.FileSystem.FileManager.Download, L("Permission:DownloadFile")); |
|||
} |
|||
|
|||
private static LocalizableString L(string name) |
|||
{ |
|||
return LocalizableString.Create<AbpFileManagementResource>(name); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
namespace LINGYUN.Abp.FileManagement.Permissions |
|||
{ |
|||
public class AbpFileManagementPermissions |
|||
{ |
|||
public const string GroupName = "Abp.FileManagement"; |
|||
|
|||
/// <summary>
|
|||
/// 文件系统
|
|||
/// </summary>
|
|||
public class FileSystem |
|||
{ |
|||
public const string Default = GroupName + ".FileSystem"; |
|||
|
|||
public const string Create = Default + ".Create"; |
|||
|
|||
public const string Delete = Default + ".Delete"; |
|||
|
|||
public const string Update = Default + ".Update"; |
|||
|
|||
public const string Copy = Default + ".Copy"; |
|||
|
|||
public const string Move = Default + ".Move"; |
|||
/// <summary>
|
|||
/// 文件管理
|
|||
/// </summary>
|
|||
public class FileManager |
|||
{ |
|||
public const string Default = FileSystem.Default + ".FileManager"; |
|||
|
|||
public const string Create = Default + ".Create"; |
|||
|
|||
public const string Copy = Default + ".Copy"; |
|||
|
|||
public const string Delete = Default + ".Delete"; |
|||
|
|||
public const string Update = Default + ".Update"; |
|||
|
|||
public const string Move = Default + ".Move"; |
|||
|
|||
public const string Download = Default + ".Download"; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\LINGYUN.Abp.FileManagement.Application.Contracts\LINGYUN.Abp.FileManagement.Application.Contracts.csproj" /> |
|||
<ProjectReference Include="..\LINGYUN.Abp.FileManagement.Domain\LINGYUN.Abp.FileManagement.Domain.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,12 @@ |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace LINGYUN.Abp.FileManagement |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpFileManagementDomainModule), |
|||
typeof(AbpFileManagementApplicationContractsModule))] |
|||
public class AbpFileManagementApplicationModule : AbpModule |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Text; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace LINGYUN.Abp.FileManagement |
|||
{ |
|||
public class FileManagementApplicationServiceBase : ApplicationService |
|||
{ |
|||
protected FileManagementApplicationServiceBase() |
|||
{ |
|||
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,392 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.ComponentModel.DataAnnotations; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.BlobStoring; |
|||
using Volo.Abp.BlobStoring.FileSystem; |
|||
|
|||
namespace LINGYUN.Abp.FileManagement |
|||
{ |
|||
public class FileSystemAppService : FileManagementApplicationServiceBase, IFileSystemAppService |
|||
{ |
|||
protected IBlobContainer<FileSystemContainer> BlobContainer { get; } |
|||
protected IBlobContainerConfigurationProvider BlobContainerConfigurationProvider { get; } |
|||
public FileSystemAppService( |
|||
IBlobContainer<FileSystemContainer> blobContainer, |
|||
IBlobContainerConfigurationProvider blobContainerConfigurationProvider) |
|||
{ |
|||
BlobContainer = blobContainer; |
|||
BlobContainerConfigurationProvider = blobContainerConfigurationProvider; |
|||
} |
|||
|
|||
public virtual Task CopyFileAsync(FileCopyOrMoveDto input) |
|||
{ |
|||
string fileSystemPath = GetFileSystemPath(input.Path); |
|||
var fileFullName = Path.Combine(fileSystemPath, input.Name); |
|||
if (!File.Exists(fileFullName)) |
|||
{ |
|||
throw new UserFriendlyException("指定的文件不存在!"); |
|||
} |
|||
var copyToFilePath = GetFileSystemPath(input.ToPath); |
|||
var copyToFileFullName = Path.Combine(copyToFilePath, input.ToName ?? input.Name); |
|||
if (File.Exists(copyToFileFullName)) |
|||
{ |
|||
throw new UserFriendlyException("指定的路径中已经有相同的文件名存在!"); |
|||
} |
|||
|
|||
File.Copy(fileFullName, copyToFileFullName); |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
public virtual Task CopyFolderAsync([Required, StringLength(255)] string path, FolderCopyDto input) |
|||
{ |
|||
string fileSystemPath = GetFileSystemPath(path); |
|||
if (!Directory.Exists(fileSystemPath)) |
|||
{ |
|||
throw new UserFriendlyException("指定目录不存在!"); |
|||
} |
|||
var copyToFilePath = GetFileSystemPath(input.CopyToPath); |
|||
if (Directory.Exists(copyToFilePath)) |
|||
{ |
|||
throw new UserFriendlyException("指定的路径中已经有同名的目录存在!"); |
|||
} |
|||
|
|||
CopyDirectory(fileSystemPath, copyToFilePath); |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
public virtual async Task CreateFileAsync(FileCreateDto input) |
|||
{ |
|||
string fileSystemPath = GetFileSystemPath(input.Path); |
|||
var fileFullName = Path.Combine(fileSystemPath, input.Name); |
|||
if (File.Exists(fileFullName) && !input.Rewrite) |
|||
{ |
|||
throw new UserFriendlyException("指定的文件已经存在!"); |
|||
} |
|||
await BlobContainer.SaveAsync(input.Name, input.Data, input.Rewrite); |
|||
} |
|||
|
|||
public virtual Task CreateFolderAsync(FolderCreateDto input) |
|||
{ |
|||
string fileSystemPath = GetFileSystemBashPath(); |
|||
if (!input.Parent.IsNullOrWhiteSpace()) |
|||
{ |
|||
fileSystemPath = GetFileSystemPath(input.Parent); |
|||
} |
|||
var newFloderPath = Path.Combine(fileSystemPath, input.Path); |
|||
if (Directory.Exists(newFloderPath)) |
|||
{ |
|||
throw new UserFriendlyException("指定目录已经存在!"); |
|||
} |
|||
Directory.CreateDirectory(newFloderPath); |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
public virtual Task DeleteFileAsync(FileDeleteDto input) |
|||
{ |
|||
var fileSystemPath = GetFileSystemPath(input.Path); |
|||
fileSystemPath = Path.Combine(fileSystemPath, input.Name); |
|||
if (File.Exists(fileSystemPath)) |
|||
{ |
|||
File.Delete(fileSystemPath); |
|||
} |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
public virtual Task DeleteFolderAsync([Required, StringLength(255)] string path) |
|||
{ |
|||
string fileSystemPath = GetFileSystemPath(path); |
|||
if (!Directory.Exists(fileSystemPath)) |
|||
{ |
|||
throw new UserFriendlyException("指定目录不存在!"); |
|||
} |
|||
var fileSystemChildrenPath = Directory.GetDirectories(fileSystemPath); |
|||
if (fileSystemChildrenPath.Length > 0) |
|||
{ |
|||
throw new UserFriendlyException("指定的目录不为空,不可删除此目录!"); |
|||
} |
|||
var fileSystemPathFiles = Directory.GetFiles(fileSystemPath); |
|||
if (fileSystemPathFiles.Length > 0) |
|||
{ |
|||
throw new UserFriendlyException("指定的目录不为空,不可删除此目录!"); |
|||
} |
|||
Directory.Delete(fileSystemPath); |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
public virtual async Task<Stream> DownloadFileAsync(FileSystemGetDto input) |
|||
{ |
|||
var fileSystemPath = GetFileSystemPath(input.Path); |
|||
fileSystemPath = Path.Combine(fileSystemPath, input.Name); |
|||
var blobName = GetFileSystemRelativePath(fileSystemPath); |
|||
|
|||
return await BlobContainer.GetAsync(blobName); |
|||
} |
|||
|
|||
public virtual Task<FileSystemDto> GetAsync(FileSystemGetDto input) |
|||
{ |
|||
var fileSystemPath = GetFileSystemPath(input.Path); |
|||
fileSystemPath = Path.Combine(fileSystemPath, input.Name); |
|||
if (File.Exists(fileSystemPath)) |
|||
{ |
|||
var fileInfo = new FileInfo(fileSystemPath); |
|||
var fileSystem = new FileSystemDto |
|||
{ |
|||
Type = FileSystemType.File, |
|||
Name = fileInfo.Name, |
|||
Size = fileInfo.Length, |
|||
CreationTime = fileInfo.CreationTime, |
|||
LastModificationTime = fileInfo.LastWriteTime |
|||
}; |
|||
if (fileInfo.Directory?.Parent != null && !fileInfo.Directory.Parent.Name.IsNullOrWhiteSpace()) |
|||
{ |
|||
fileSystem.Parent = GetFileSystemRelativePath(fileInfo.Directory.Parent.FullName); |
|||
} |
|||
return Task.FromResult(fileSystem); |
|||
} |
|||
if (Directory.Exists(fileSystemPath)) |
|||
{ |
|||
var directoryInfo = new DirectoryInfo(fileSystemPath); |
|||
var fileSystem = new FileSystemDto |
|||
{ |
|||
Type = FileSystemType.Folder, |
|||
Name = directoryInfo.Name, |
|||
CreationTime = directoryInfo.CreationTime, |
|||
LastModificationTime = directoryInfo.LastWriteTime |
|||
}; |
|||
if (directoryInfo.Parent != null && !directoryInfo.Parent.Name.IsNullOrWhiteSpace()) |
|||
{ |
|||
fileSystem.Parent = GetFileSystemRelativePath(directoryInfo.Parent.FullName); |
|||
} |
|||
return Task.FromResult(fileSystem); |
|||
} |
|||
throw new UserFriendlyException("文件或目录不存在!"); |
|||
} |
|||
|
|||
public virtual Task<PagedResultDto<FileSystemDto>> GetListAsync(GetFileSystemListDto input) |
|||
{ |
|||
List<FileSystemDto> fileSystems = new List<FileSystemDto>(); |
|||
|
|||
string fileSystemPath = GetFileSystemBashPath(); |
|||
if (!input.Parent.IsNullOrWhiteSpace()) |
|||
{ |
|||
fileSystemPath = GetFileSystemPath(input.Parent); |
|||
} |
|||
var directoryInfo = new DirectoryInfo(fileSystemPath); |
|||
// 查询全部
|
|||
var fileSystemInfos = directoryInfo.GetFileSystemInfos(); |
|||
// 指定搜索条件查询目录
|
|||
FileSystemInfo[] fileSystemInfoSearchChildren;// = directoryInfo.GetDirectories(input.Filter ?? "*", SearchOption.TopDirectoryOnly);
|
|||
if (!input.Filter.IsNullOrWhiteSpace()) |
|||
{ |
|||
var searchPattern = $"*{input.Filter}*"; |
|||
fileSystemInfoSearchChildren = directoryInfo.GetFileSystemInfos(searchPattern); |
|||
} |
|||
else |
|||
{ |
|||
fileSystemInfoSearchChildren = directoryInfo.GetFileSystemInfos(); |
|||
} |
|||
|
|||
fileSystemInfoSearchChildren = fileSystemInfoSearchChildren |
|||
.Skip((input.SkipCount - 1) * input.MaxResultCount) |
|||
.Take(input.MaxResultCount) |
|||
.ToArray(); |
|||
|
|||
foreach (var fileSystemInfo in fileSystemInfoSearchChildren) |
|||
{ |
|||
var fileSystem = new FileSystemDto |
|||
{ |
|||
Name = fileSystemInfo.Name, |
|||
CreationTime = fileSystemInfo.CreationTime, |
|||
LastModificationTime = fileSystemInfo.LastWriteTime, |
|||
}; |
|||
if (fileSystemInfo is FileInfo fileInfo) |
|||
{ |
|||
fileSystem.Type = FileSystemType.File; |
|||
fileSystem.Size = fileInfo.Length; |
|||
if (fileInfo.Directory?.Parent != null && !fileInfo.Directory.Parent.Name.IsNullOrWhiteSpace()) |
|||
{ |
|||
fileSystem.Parent = GetFileSystemRelativePath(fileInfo.Directory.Parent.FullName); |
|||
} |
|||
} |
|||
else if (fileSystemInfo is DirectoryInfo directory) |
|||
{ |
|||
fileSystem.Type = FileSystemType.Folder; |
|||
if (directory.Parent != null && !directory.Parent.Name.IsNullOrWhiteSpace()) |
|||
{ |
|||
fileSystem.Parent = GetFileSystemRelativePath(directory.Parent.FullName); |
|||
} |
|||
} |
|||
fileSystems.Add(fileSystem); |
|||
} |
|||
|
|||
return Task.FromResult(new PagedResultDto<FileSystemDto>( |
|||
fileSystemInfos.Length, fileSystems |
|||
)); |
|||
} |
|||
|
|||
public virtual Task MoveFileAsync(FileCopyOrMoveDto input) |
|||
{ |
|||
string fileSystemPath = GetFileSystemPath(input.Path); |
|||
fileSystemPath = Path.Combine(fileSystemPath, input.Name); |
|||
if (!File.Exists(fileSystemPath)) |
|||
{ |
|||
throw new UserFriendlyException("指定目录不存在!"); |
|||
} |
|||
var moveToFilePath = GetFileSystemPath(input.ToPath); |
|||
moveToFilePath = Path.Combine(moveToFilePath, input.ToName ?? input.Name); |
|||
if (Directory.Exists(moveToFilePath)) |
|||
{ |
|||
throw new UserFriendlyException("指定的路径中已经有同名的文件存在!"); |
|||
} |
|||
|
|||
File.Move(fileSystemPath, moveToFilePath); |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
public virtual Task MoveFolderAsync([Required, StringLength(255)] string path, FolderMoveDto input) |
|||
{ |
|||
string fileSystemPath = GetFileSystemPath(path); |
|||
if (!Directory.Exists(fileSystemPath)) |
|||
{ |
|||
throw new UserFriendlyException("指定目录不存在!"); |
|||
} |
|||
var moveToFilePath = GetFileSystemPath(input.MoveToPath); |
|||
if (Directory.Exists(moveToFilePath)) |
|||
{ |
|||
throw new UserFriendlyException("指定的路径中已经有同名的目录存在!"); |
|||
} |
|||
|
|||
Directory.Move(fileSystemPath, moveToFilePath); |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
public virtual Task<FileSystemDto> UpdateAsync([Required, StringLength(255)] string name, FileSystemUpdateDto input) |
|||
{ |
|||
string fileSystemPath = GetFileSystemPath(name); |
|||
var renameFilePath = GetFileSystemPath(input.NewName); |
|||
if (File.Exists(fileSystemPath)) |
|||
{ |
|||
if (File.Exists(renameFilePath)) |
|||
{ |
|||
throw new UserFriendlyException("指定的文件名已经存在!"); |
|||
} |
|||
File.Move(fileSystemPath, renameFilePath); |
|||
|
|||
var fileInfo = new FileInfo(renameFilePath); |
|||
var fileSystem = new FileSystemDto |
|||
{ |
|||
Type = FileSystemType.File, |
|||
Name = fileInfo.Name, |
|||
Size = fileInfo.Length, |
|||
CreationTime = fileInfo.CreationTime, |
|||
LastModificationTime = fileInfo.LastWriteTime |
|||
}; |
|||
if (fileInfo.Directory?.Parent != null && !fileInfo.Directory.Parent.Name.IsNullOrWhiteSpace()) |
|||
{ |
|||
fileSystem.Parent = GetFileSystemRelativePath(fileInfo.Directory.Parent.FullName); |
|||
} |
|||
return Task.FromResult(fileSystem); |
|||
} |
|||
if (Directory.Exists(fileSystemPath)) |
|||
{ |
|||
if (Directory.Exists(renameFilePath)) |
|||
{ |
|||
throw new UserFriendlyException("指定的路径中已经有同名的目录存在!"); |
|||
} |
|||
|
|||
Directory.Move(fileSystemPath, renameFilePath); |
|||
|
|||
var directoryInfo = new DirectoryInfo(renameFilePath); |
|||
var fileSystem = new FileSystemDto |
|||
{ |
|||
Type = FileSystemType.Folder, |
|||
Name = directoryInfo.Name, |
|||
CreationTime = directoryInfo.CreationTime, |
|||
LastModificationTime = directoryInfo.LastWriteTime |
|||
}; |
|||
if (directoryInfo.Parent != null && !directoryInfo.Parent.Name.IsNullOrWhiteSpace()) |
|||
{ |
|||
fileSystem.Parent = GetFileSystemRelativePath(directoryInfo.Parent.FullName); |
|||
} |
|||
return Task.FromResult(fileSystem); |
|||
} |
|||
throw new UserFriendlyException("文件或目录不存在!"); |
|||
} |
|||
|
|||
protected virtual string GetFileSystemRelativePath(string path) |
|||
{ |
|||
return path.Replace(Directory.GetCurrentDirectory(), ""); |
|||
} |
|||
|
|||
protected virtual string GetFileSystemPath(string path) |
|||
{ |
|||
var fileSystemConfiguration = GetFileSystemBlobProviderConfiguration(); |
|||
var blobPath = GetFileSystemBashPath(); |
|||
|
|||
if (fileSystemConfiguration.AppendContainerNameToBasePath) |
|||
{ |
|||
blobPath = Path.Combine(blobPath, path); |
|||
} |
|||
|
|||
return blobPath; |
|||
} |
|||
|
|||
protected virtual string GetFileSystemBashPath() |
|||
{ |
|||
var fileSystemConfiguration = GetFileSystemBlobProviderConfiguration(); |
|||
var blobPath = fileSystemConfiguration.BasePath; |
|||
blobPath = Path.Combine(Directory.GetCurrentDirectory(), blobPath); |
|||
if (CurrentTenant.Id == null) |
|||
{ |
|||
blobPath = Path.Combine(blobPath, "host"); |
|||
} |
|||
else |
|||
{ |
|||
blobPath = Path.Combine(blobPath, "tenants", CurrentTenant.Id.Value.ToString("D")); |
|||
} |
|||
|
|||
return blobPath; |
|||
} |
|||
|
|||
protected virtual FileSystemBlobProviderConfiguration GetFileSystemBlobProviderConfiguration() |
|||
{ |
|||
var blobConfiguration = BlobContainerConfigurationProvider |
|||
.Get<FileSystemContainer>(); |
|||
return blobConfiguration.GetFileSystemConfiguration(); |
|||
} |
|||
|
|||
protected void CopyDirectory(string sourcePath, string copyToPath) |
|||
{ |
|||
var sourceDirectory = new DirectoryInfo(sourcePath); |
|||
var fileSystemInfos = sourceDirectory.GetFileSystemInfos(); |
|||
|
|||
foreach (var fileSystemInfo in fileSystemInfos) |
|||
{ |
|||
var copyToFilePath = Path.Combine(copyToPath, fileSystemInfo.Name); |
|||
if (fileSystemInfo is DirectoryInfo) |
|||
{ |
|||
if (!Directory.Exists(copyToFilePath)) |
|||
{ |
|||
Directory.CreateDirectory(copyToFilePath); |
|||
} |
|||
CopyDirectory(fileSystemInfo.FullName, copyToFilePath); |
|||
} |
|||
else |
|||
{ |
|||
File.Copy(fileSystemInfo.FullName, copyToFilePath, true); |
|||
} |
|||
} |
|||
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<None Remove="LINGYUN\Abp\FileManagement\Localization\Resources\en.json" /> |
|||
<None Remove="LINGYUN\Abp\FileManagement\Localization\Resources\zh-Hans.json" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<EmbeddedResource Include="LINGYUN\Abp\FileManagement\Localization\Resources\en.json" /> |
|||
<EmbeddedResource Include="LINGYUN\Abp\FileManagement\Localization\Resources\zh-Hans.json" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.Validation" Version="3.0.0" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,30 @@ |
|||
using LINGYUN.Abp.FileManagement.Localization; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.Validation; |
|||
using Volo.Abp.Validation.Localization; |
|||
using Volo.Abp.VirtualFileSystem; |
|||
|
|||
namespace LINGYUN.Abp.FileManagement |
|||
{ |
|||
[DependsOn(typeof(AbpValidationModule))] |
|||
public class AbpFileManagementDomainSharedModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpVirtualFileSystemOptions>(options => |
|||
{ |
|||
options.FileSets.AddEmbedded<AbpFileManagementDomainSharedModule>(); |
|||
}); |
|||
|
|||
Configure<AbpLocalizationOptions>(options => |
|||
{ |
|||
options.Resources |
|||
.Add<AbpFileManagementResource>("en") |
|||
.AddBaseTypes( |
|||
typeof(AbpValidationResource) |
|||
).AddVirtualJson("/LINGYUN/Abp/FileManagement/Localization/Resources"); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using Volo.Abp.Localization; |
|||
|
|||
namespace LINGYUN.Abp.FileManagement.Localization |
|||
{ |
|||
[LocalizationResourceName("AbpFileManagement")] |
|||
public class AbpFileManagementResource |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
{ |
|||
"culture": "en", |
|||
"texts": { |
|||
"Permission:FileManagement": "File management", |
|||
"Permission:FileSystem": "File system", |
|||
"Permission:FileManager": "Files", |
|||
"Permission:CreateFolder": "Create directory", |
|||
"Permission:DeleteFolder": "Delete directory", |
|||
"Permission:UpdateFolder": "Edit directory", |
|||
"Permission:MoveFolder": "Change directory", |
|||
"Permission:CopyFolder": "Copy directory", |
|||
"Permission:AppendFile": "Add files", |
|||
"Permission:UpdateFile": "Change file", |
|||
"Permission:DeleteFile": "Delete file", |
|||
"Permission:CopyFile": "Copy file", |
|||
"Permission:MoveFile": "Move file", |
|||
"Permission:DownloadFile": "Download file", |
|||
"UploadFileSizeBeyondLimit": "Upload file size cannot exceed {0} MB!", |
|||
"NotAllowedFileExtensionName": "Not allowed file extension: {0}!", |
|||
"DisplayName:FileLimitLength": "File limit size", |
|||
"Description:FileLimitLength": "Limit size of uploaded file in MB", |
|||
"DisplayName:AllowFileExtensions": "File extension", |
|||
"Description:AllowFileExtensions": "List of allowed extensions to upload files, with multiple extensions separated by, don't need a notation" |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
{ |
|||
"culture": "zh-Hans", |
|||
"texts": { |
|||
"Permission:FileManagement": "文件管理", |
|||
"Permission:FileSystem": "文件系统", |
|||
"Permission:FileManager": "文件", |
|||
"Permission:CreateFolder": "创建目录", |
|||
"Permission:DeleteFolder": "删除目录", |
|||
"Permission:UpdateFolder": "修改目录", |
|||
"Permission:MoveFolder": "变更目录", |
|||
"Permission:CopyFolder": "复制目录", |
|||
"Permission:AppendFile": "添加文件", |
|||
"Permission:UpdateFile": "变更文件", |
|||
"Permission:DeleteFile": "删除文件", |
|||
"Permission:CopyFile": "复制文件", |
|||
"Permission:MoveFile": "移动文件", |
|||
"Permission:DownloadFile": "下载文件", |
|||
"UploadFileSizeBeyondLimit": "上传文件大小不能超过 {0} MB!", |
|||
"NotAllowedFileExtensionName": "不被允许的文件扩展名: {0}!", |
|||
"DisplayName:FileLimitLength": "文件限制大小", |
|||
"Description:FileLimitLength": "上传文件的限制大小,单位(MB)", |
|||
"DisplayName:AllowFileExtensions": "文件扩展名", |
|||
"Description:AllowFileExtensions": "允许的上传文件扩展名列表,多个扩展名以,分隔,无需输入.符号" |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
namespace LINGYUN.Abp.FileManagement.Settings |
|||
{ |
|||
public class AbpFileManagementSettingNames |
|||
{ |
|||
public const string GroupName = "Abp.FileManagement"; |
|||
/// <summary>
|
|||
/// 文件限制长度
|
|||
/// </summary>
|
|||
public const string FileLimitLength = GroupName + ".FileLimitLength"; |
|||
/// <summary>
|
|||
/// 允许的文件扩展名类型
|
|||
/// </summary>
|
|||
public const string AllowFileExtensions = GroupName + ".AllowFileExtensions"; |
|||
|
|||
public const int DefaultFileLimitLength = 100; |
|||
public const string DefaultAllowFileExtensions = "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"; |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.BlobStoring.FileSystem" Version="3.0.0" /> |
|||
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="3.0.0" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\LINGYUN.Abp.FileManagement.Domain.Shared\LINGYUN.Abp.FileManagement.Domain.Shared.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,15 @@ |
|||
using Volo.Abp.Domain; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace LINGYUN.Abp.FileManagement |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpDddDomainModule), |
|||
typeof(AbpMultiTenancyModule), |
|||
typeof(AbpFileManagementDomainSharedModule) |
|||
)] |
|||
public class AbpFileManagementDomainModule : AbpModule |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using Volo.Abp.BlobStoring; |
|||
|
|||
namespace LINGYUN.Abp.FileManagement |
|||
{ |
|||
[BlobContainerName("abp-file-management")] |
|||
public class FileSystemContainer |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
using LINGYUN.Abp.FileManagement.Localization; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.Settings; |
|||
|
|||
namespace LINGYUN.Abp.FileManagement.Settings |
|||
{ |
|||
public class AbpFileManagementSettingDefinitionProvider : SettingDefinitionProvider |
|||
{ |
|||
public override void Define(ISettingDefinitionContext context) |
|||
{ |
|||
context.Add(CreateFileSystemSettings()); |
|||
} |
|||
|
|||
protected SettingDefinition[] CreateFileSystemSettings() |
|||
{ |
|||
return new SettingDefinition[] |
|||
{ |
|||
new SettingDefinition( |
|||
name: AbpFileManagementSettingNames.FileLimitLength, |
|||
defaultValue: AbpFileManagementSettingNames.DefaultFileLimitLength.ToString(), |
|||
displayName: L("DisplayName:FileLimitLength"), |
|||
description: L("Description:FileLimitLength"), |
|||
isVisibleToClients: true) |
|||
.WithProviders( |
|||
GlobalSettingValueProvider.ProviderName, |
|||
TenantSettingValueProvider.ProviderName), |
|||
new SettingDefinition( |
|||
name: AbpFileManagementSettingNames.AllowFileExtensions, |
|||
defaultValue: AbpFileManagementSettingNames.DefaultAllowFileExtensions, |
|||
displayName: L("DisplayName:AllowFileExtensions"), |
|||
description: L("Description:AllowFileExtensions"), |
|||
isVisibleToClients: true) |
|||
.WithProviders( |
|||
GlobalSettingValueProvider.ProviderName, |
|||
TenantSettingValueProvider.ProviderName), |
|||
}; |
|||
} |
|||
|
|||
protected LocalizableString L(string name) |
|||
{ |
|||
return LocalizableString.Create<AbpFileManagementResource>(name); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netcoreapp3.1</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="3.0.0" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\LINGYUN.Abp.FileManagement.Application.Contracts\LINGYUN.Abp.FileManagement.Application.Contracts.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,21 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace LINGYUN.Abp.FileManagement |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpFileManagementApplicationContractsModule), |
|||
typeof(AbpAspNetCoreMvcModule) |
|||
)] |
|||
public class AbpFileManagementHttpApiModule : AbpModule |
|||
{ |
|||
public override void PreConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
PreConfigure<IMvcBuilder>(mvcBuilder => |
|||
{ |
|||
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpFileManagementHttpApiModule).Assembly); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,240 @@ |
|||
using LINGYUN.Abp.FileManagement.Settings; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.AspNetCore.StaticFiles; |
|||
using System; |
|||
using System.ComponentModel.DataAnnotations; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
using Volo.Abp.IO; |
|||
using Volo.Abp.Settings; |
|||
|
|||
namespace LINGYUN.Abp.FileManagement |
|||
{ |
|||
[Controller] |
|||
[RemoteService(Name = "AbpFileManagement")] |
|||
[Area("file-management")] |
|||
[Route("api/file-management/file-system")] |
|||
public class FileSystemController : AbpController |
|||
{ |
|||
protected ISettingProvider SettingProvider { get; } |
|||
protected IFileSystemAppService FileSystemAppService { get; } |
|||
|
|||
public FileSystemController( |
|||
ISettingProvider settingProvider, |
|||
IFileSystemAppService fileSystemAppService) |
|||
{ |
|||
SettingProvider = settingProvider; |
|||
FileSystemAppService = fileSystemAppService; |
|||
} |
|||
|
|||
[HttpPut] |
|||
[Route("files/copy")] |
|||
public virtual async Task CopyFileAsync(FileCopyOrMoveDto input) |
|||
{ |
|||
await FileSystemAppService.CopyFileAsync(input); |
|||
} |
|||
|
|||
[HttpPut] |
|||
[Route("folders/copy")] |
|||
public virtual async Task CopyFolderAsync([Required, StringLength(255)] string path, FolderCopyDto input) |
|||
{ |
|||
await FileSystemAppService.CopyFolderAsync(path, input); |
|||
} |
|||
|
|||
[HttpPost] |
|||
[Route("files/upload")] |
|||
public virtual async Task CreateFileAsync(FileCreateDto input) |
|||
{ |
|||
// 检查文件大小
|
|||
var fileSizeLimited = await SettingProvider |
|||
.GetAsync( |
|||
AbpFileManagementSettingNames.FileLimitLength, |
|||
AbpFileManagementSettingNames.DefaultFileLimitLength); |
|||
if (fileSizeLimited * 1024 * 1024 < input.TotalByte) |
|||
{ |
|||
throw new UserFriendlyException(L["UploadFileSizeBeyondLimit", fileSizeLimited]); |
|||
} |
|||
// 采用分块模式上传文件
|
|||
|
|||
// 保存分块到临时目录
|
|||
var fileName = input.Name; |
|||
// 文件扩展名
|
|||
var fileExtensionName = FileHelper.GetExtension(fileName); |
|||
var fileAllowExtension = await SettingProvider |
|||
.GetOrNullAsync(AbpFileManagementSettingNames.AllowFileExtensions); |
|||
if (fileAllowExtension.IsNullOrWhiteSpace()) |
|||
{ |
|||
fileAllowExtension = AbpFileManagementSettingNames.DefaultAllowFileExtensions; |
|||
} |
|||
// 检查文件扩展名
|
|||
if (!fileAllowExtension.Split(',') |
|||
.Any(fe => fe.Equals(fileExtensionName, StringComparison.CurrentCultureIgnoreCase))) |
|||
{ |
|||
throw new UserFriendlyException(L["NotAllowedFileExtensionName", fileExtensionName]); |
|||
} |
|||
// 当前计算机临时目录
|
|||
var tempFilePath = Environment.GetFolderPath(Environment.SpecialFolder.Templates); |
|||
// 以上传的文件名创建一个临时目录
|
|||
tempFilePath = Path.Combine(tempFilePath, "lingyun-abp-file-management", Path.GetFileNameWithoutExtension(fileName)); |
|||
// 以上传的分片索引创建临时文件
|
|||
var tempSavedFile = Path.Combine(tempFilePath, $"{input.CurrentByte}.{fileExtensionName}"); |
|||
if (!Directory.Exists(tempFilePath)) |
|||
{ |
|||
// 临时目录不存在则创建
|
|||
Directory.CreateDirectory(tempFilePath); |
|||
} |
|||
try |
|||
{ |
|||
if (HttpContext.RequestAborted.IsCancellationRequested) |
|||
{ |
|||
// 如果取消请求,删除临时目录
|
|||
Directory.Delete(tempFilePath, true); |
|||
return; |
|||
} |
|||
// 保存临时文件
|
|||
using (var fs = new FileStream(tempSavedFile, FileMode.Create, FileAccess.Write)) |
|||
{ |
|||
// 写入当前分片文件
|
|||
await Request.Body.CopyToAsync(fs); |
|||
} |
|||
|
|||
if (input.CurrentByte == input.TotalByte) |
|||
{ |
|||
// 合并文件
|
|||
var mergeSavedFile = Path.Combine(tempFilePath, $"{fileName}"); |
|||
// 获取并排序所有分片文件
|
|||
var mergeFiles = Directory.GetFiles(tempFilePath).OrderBy(f => f.Length).ThenBy(f => f); |
|||
// 创建临时合并文件
|
|||
using (var mergeSavedFileStream = new FileStream(mergeSavedFile, FileMode.Create)) |
|||
{ |
|||
foreach (var mergeFile in mergeFiles) |
|||
{ |
|||
// 读取当前文件字节
|
|||
var mergeFileBytes = await FileHelper.ReadAllBytesAsync(mergeFile); |
|||
// 写入到合并文件流
|
|||
await mergeSavedFileStream.WriteAsync(mergeFileBytes, 0, mergeFileBytes.Length); |
|||
// 删除已参与合并的临时文件分片
|
|||
FileHelper.DeleteIfExists(mergeFile); |
|||
} |
|||
// 读取文件数据
|
|||
var fileData = await mergeSavedFileStream.GetAllBytesAsync(); |
|||
input.Data = fileData; |
|||
} |
|||
await FileSystemAppService.CreateFileAsync(input); |
|||
// 文件保存之后删除临时文件目录
|
|||
Directory.Delete(tempFilePath, true); |
|||
} |
|||
} |
|||
catch |
|||
{ |
|||
// 发生异常删除临时文件目录
|
|||
Directory.Delete(tempFilePath, true); |
|||
throw; |
|||
} |
|||
} |
|||
|
|||
[HttpPost] |
|||
[Route("folders/add")] |
|||
public virtual async Task CreateFolderAsync(FolderCreateDto input) |
|||
{ |
|||
await FileSystemAppService.CreateFolderAsync(input); |
|||
} |
|||
|
|||
[HttpDelete] |
|||
[Route("files/delete")] |
|||
public virtual async Task DeleteFileAsync(FileDeleteDto input) |
|||
{ |
|||
await FileSystemAppService.DeleteFileAsync(input); |
|||
} |
|||
|
|||
[HttpDelete] |
|||
[Route("folders/delete")] |
|||
public virtual async Task DeleteFolderAsync([Required, StringLength(255)] string path) |
|||
{ |
|||
await FileSystemAppService.DeleteFolderAsync(path); |
|||
} |
|||
|
|||
[HttpGet] |
|||
[Route("files/download")] |
|||
public virtual async Task DownloadFileAsync(FileSystemGetDto input) |
|||
{ |
|||
var fileStream = await FileSystemAppService.DownloadFileAsync(input); |
|||
|
|||
// 得到文件扩展名
|
|||
var fileExt = Path.GetExtension(input.Name); |
|||
var provider = new FileExtensionContentTypeProvider(); |
|||
// Http响应标头的文件类型
|
|||
string memi = provider.Mappings[fileExt]; |
|||
using (Response.Body) |
|||
{ |
|||
// Http响应标头的文件类型
|
|||
Response.ContentType = memi; |
|||
// 文件大小
|
|||
byte[] contentBytes = await fileStream.GetAllBytesAsync(); |
|||
long contentLength = contentBytes.Length; |
|||
// 指定响应内容大小
|
|||
Response.ContentLength = contentLength; |
|||
// 单个分块大小 2MB
|
|||
int bufferSize = 2 * 1024 * 1024; |
|||
// 分块总数
|
|||
int contentByteCount = Math.DivRem(contentBytes.Length, bufferSize, out int modResult); |
|||
for (int index = 0; index < contentByteCount; index++) |
|||
{ |
|||
// 当前分页传输字节
|
|||
byte[] currentTransferBytes = new byte[bufferSize]; |
|||
if (index == contentByteCount - 1) |
|||
{ |
|||
// 最后一个分块和余数大小一起传输
|
|||
if (modResult > 0) |
|||
{ |
|||
currentTransferBytes = new byte[bufferSize + modResult]; |
|||
} |
|||
} |
|||
// 复制文件流中的当前分块区段
|
|||
Array.Copy(contentBytes, index * bufferSize, currentTransferBytes, 0, currentTransferBytes.Length); |
|||
// 写入响应流
|
|||
await Response.Body.WriteAsync(currentTransferBytes, 0, currentTransferBytes.Length); |
|||
// 清空缓冲区
|
|||
await Response.Body.FlushAsync(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
[HttpGet] |
|||
[Route("profile")] |
|||
public virtual async Task<FileSystemDto> GetAsync(FileSystemGetDto input) |
|||
{ |
|||
return await FileSystemAppService.GetAsync(input); |
|||
} |
|||
|
|||
[HttpGet] |
|||
public virtual async Task<PagedResultDto<FileSystemDto>> GetListAsync(GetFileSystemListDto input) |
|||
{ |
|||
return await FileSystemAppService.GetListAsync(input); |
|||
} |
|||
|
|||
[HttpPut] |
|||
[Route("files/move")] |
|||
public virtual async Task MoveFileAsync(FileCopyOrMoveDto input) |
|||
{ |
|||
await FileSystemAppService.MoveFileAsync(input); |
|||
} |
|||
|
|||
[HttpPut] |
|||
[Route("folders/move")] |
|||
public virtual async Task MoveFolderAsync([Required, StringLength(255)] string path, FolderMoveDto input) |
|||
{ |
|||
await FileSystemAppService.MoveFolderAsync(path, input); |
|||
} |
|||
|
|||
[HttpPut] |
|||
public virtual async Task<FileSystemDto> UpdateAsync([Required, StringLength(255)] string name, FileSystemUpdateDto input) |
|||
{ |
|||
return await FileSystemAppService.UpdateAsync(name, input); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue