Browse Source

Implement upload and download interface of OSS

pull/216/head
cKey 5 years ago
parent
commit
061cd1c2cb
  1. 32
      aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/README.md
  2. 6
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/CreateOssObjectInput.cs
  3. 21
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileCopyOrMoveDto.cs
  4. 32
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileCreateDto.cs
  5. 14
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileDeleteDto.cs
  6. 15
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileSystemDownloadDto.cs
  7. 15
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileSystemDto.cs
  8. 14
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileSystemGetDto.cs
  9. 8
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileSystemType.cs
  10. 11
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileSystemUpdateDto.cs
  11. 11
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FolderCopyDto.cs
  12. 13
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FolderCreateDto.cs
  13. 11
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FolderMoveDto.cs
  14. 14
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/GetFileSystemListDto.cs
  15. 35
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/IFileSystemAppService.cs
  16. 467
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application/LINGYUN/Abp/FileManagement/FileSystemAppService.cs
  17. 8
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/FileManagementErrorCodes.cs
  18. 1
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/Localization/Resources/en.json
  19. 1
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/Localization/Resources/zh-Hans.json
  20. 2
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain/LINGYUN.Abp.FileManagement.Domain.csproj
  21. 61
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.FileSystem/LINGYUN/Abp/FileManagement/FileSystem/FileSystemOssContainer.cs
  22. 265
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN/Abp/FileManagement/FileSystemController.cs
  23. 35
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN/Abp/FileManagement/FileUploadDto.cs
  24. 96
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN/Abp/FileManagement/FileValidater.cs
  25. 9
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN/Abp/FileManagement/IFileValidater.cs
  26. 96
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN/Abp/FileManagement/OssObjectController.cs
  27. 37
      aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN/Abp/FileManagement/UploadOssObjectInput.cs
  28. 52
      vueJs/src/api/oss-manager.ts
  29. 131
      vueJs/src/views/oss-management/components/OssObjectUploadDialog.vue
  30. 78
      vueJs/src/views/oss-management/index.vue

32
aspnet-core/modules/cloud-aliyun/LINGYUN.Abp.Aliyun/README.md

@ -1,31 +1,3 @@
# LINGYUN.Abp.Aliyun # Oss-Management
阿里云sdk集成 File-Management更名为Oss-Management
参照:https://help.aliyun.com/document_detail/28763.html
## 配置使用
模块按需引用
```csharp
[DependsOn(typeof(AbpAliyunModule))]
public class YouProjectModule : AbpModule
{
// other
}
```
## 配置项说明
* AliyunSettingNames.Authorization.RegionId 可选,区域,默认 default
* AliyunSettingNames.Authorization.AccessKeyId 必须,阿里云RAM账号的AccessKey ID
* AliyunSettingNames.Authorization.AccessKeySecret 必须,RAM账号的AccessKey Secret
* AliyunSettingNames.Authorization.UseSecurityTokenService 可选,建议,使用STS Token访问,按照阿里云文档,建议使用Sts Token访问API,默认false
* AliyunSettingNames.Authorization.RamRoleArn 可选,启用Sts Token之后必须配置,阿里云RAM角色ARN
* AliyunSettingNames.Authorization.RoleSessionName 可选,启用Sts Token之后的用户自定义令牌名称,用于访问审计
* AliyunSettingNames.Authorization.DurationSeconds 可选,用户令牌的过期时间,单位为秒,默认3000
* AliyunSettingNames.Authorization.Policy 可选,权限策略,为json字符串
## 其他
网络因素在高并发下可能会出现预期外的异常,考虑使用二级缓存

6
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/CreateOssObjectInput.cs

@ -1,5 +1,7 @@
using System; using System;
using System.IO; using System.IO;
using Volo.Abp.Auditing;
using Volo.Abp.Validation;
namespace LINGYUN.Abp.FileManagement namespace LINGYUN.Abp.FileManagement
{ {
@ -8,12 +10,16 @@ namespace LINGYUN.Abp.FileManagement
public string Bucket { get; set; } public string Bucket { get; set; }
public string Path { get; set; } public string Path { get; set; }
public string Object { get; set; } public string Object { get; set; }
[DisableAuditing]
[DisableValidation]
public Stream Content { get; set; } public Stream Content { get; set; }
public TimeSpan? ExpirationTime { get; set; } public TimeSpan? ExpirationTime { get; set; }
public void SetContent(Stream content) public void SetContent(Stream content)
{ {
Content = content; Content = content;
Content?.Seek(0, SeekOrigin.Begin);
} }
} }
} }

21
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileCopyOrMoveDto.cs

@ -1,21 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace LINGYUN.Abp.FileManagement
{
public class FileCopyOrMoveDto
{
[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; }
}
}

32
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileCreateDto.cs

@ -1,32 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.IO;
using Volo.Abp.Auditing;
using Volo.Abp.Validation;
namespace LINGYUN.Abp.FileManagement
{
public class FileCreateDto
{
/// <summary>
/// 文件名
/// </summary>
[Required]
[StringLength(255)]
public string FileName { get; set; }
/// <summary>
/// 文件路径
/// </summary>
[StringLength(255)]
public string Path { get; set; }
/// <summary>
/// 文件数据,前端无需传递此参数,由控制器传递
/// </summary>
[DisableAuditing]
[DisableValidation]// TODO: 需要禁用参数检查,否则会有一个框架方面的性能问题存在
public byte[] Data { get; set; }
/// <summary>
/// 是否覆盖文件
/// </summary>
public bool Rewrite { get; set; } = false;
}
}

14
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileDeleteDto.cs

@ -1,14 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace LINGYUN.Abp.FileManagement
{
public class FileDeleteDto
{
[StringLength(255)]
public string Path { get; set; }
[Required]
[StringLength(255)]
public string Name { get; set; }
}
}

15
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileSystemDownloadDto.cs

@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;
namespace LINGYUN.Abp.FileManagement
{
public class FileSystemDownloadDto : FileSystemGetDto
{
/// <summary>
/// 当前字节数
/// </summary>
public int CurrentByte { get; set; }
}
}

15
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileSystemDto.cs

@ -1,15 +0,0 @@
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 string Extension { get; set; }
public long? Size { get; set; }
public DateTime CreationTime { get; set; }
public DateTime? LastModificationTime { get; set; }
}
}

14
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileSystemGetDto.cs

@ -1,14 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace LINGYUN.Abp.FileManagement
{
public class FileSystemGetDto
{
[StringLength(255)]
public string Path { get; set; }
[Required]
[StringLength(255)]
public string Name { get; set; }
}
}

8
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileSystemType.cs

@ -1,8 +0,0 @@
namespace LINGYUN.Abp.FileManagement
{
public enum FileSystemType
{
Folder = 0,
File = 1
}
}

11
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FileSystemUpdateDto.cs

@ -1,11 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace LINGYUN.Abp.FileManagement
{
public class FileSystemUpdateDto
{
[Required]
[StringLength(255)]
public string NewName { get; set; }
}
}

11
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FolderCopyDto.cs

@ -1,11 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace LINGYUN.Abp.FileManagement
{
public class FolderCopyDto
{
[Required]
[StringLength(255)]
public string CopyToPath { get; set; }
}
}

13
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FolderCreateDto.cs

@ -1,13 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace LINGYUN.Abp.FileManagement
{
public class FolderCreateDto
{
[Required]
[StringLength(255)]
public string Path { get; set; }
public string Parent { get; set; }
}
}

11
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/FolderMoveDto.cs

@ -1,11 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace LINGYUN.Abp.FileManagement
{
public class FolderMoveDto
{
[Required]
[StringLength(255)]
public string MoveToPath { get; set; }
}
}

14
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/GetFileSystemListDto.cs

@ -1,14 +0,0 @@
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; }
}
}

35
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application.Contracts/LINGYUN/Abp/FileManagement/IFileSystemAppService.cs

@ -1,35 +0,0 @@
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);
}
}

467
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Application/LINGYUN/Abp/FileManagement/FileSystemAppService.cs

@ -1,467 +0,0 @@
using LINGYUN.Abp.FileManagement.Permissions;
using Microsoft.AspNetCore.Authorization;
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
{
[Authorize(AbpFileManagementPermissions.FileSystem.Default)]
public class FileSystemAppService : FileManagementApplicationServiceBase, IFileSystemAppService
{
protected IBlobContainer<AbpFileManagementContainer> BlobContainer { get; }
protected IBlobContainerConfigurationProvider BlobContainerConfigurationProvider { get; }
public FileSystemAppService(
IBlobContainer<AbpFileManagementContainer> blobContainer,
IBlobContainerConfigurationProvider blobContainerConfigurationProvider)
{
BlobContainer = blobContainer;
BlobContainerConfigurationProvider = blobContainerConfigurationProvider;
}
[Authorize(AbpFileManagementPermissions.FileSystem.FileManager.Copy)]
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(L["FilePathNotFound"]);
}
var copyToFilePath = GetFileSystemPath(input.ToPath);
var copyToFileFullName = Path.Combine(copyToFilePath, input.ToName ?? input.Name);
if (File.Exists(copyToFileFullName))
{
throw new UserFriendlyException(L["FilePathAlreadyExists"]);
}
File.Copy(fileFullName, copyToFileFullName);
return Task.CompletedTask;
}
[Authorize(AbpFileManagementPermissions.FileSystem.Copy)]
public virtual Task CopyFolderAsync([Required, StringLength(255)] string path, FolderCopyDto input)
{
string fileSystemPath = GetFileSystemPath(path);
if (!Directory.Exists(fileSystemPath))
{
throw new UserFriendlyException(L["PathNotFound"]);
}
var copyToFilePath = GetFileSystemPath(input.CopyToPath);
if (Directory.Exists(copyToFilePath))
{
throw new UserFriendlyException(L["FilePathAlreadyExists"]);
}
CopyDirectory(fileSystemPath, copyToFilePath);
return Task.CompletedTask;
}
[Authorize(AbpFileManagementPermissions.FileSystem.FileManager.Create)]
public virtual async Task CreateFileAsync(FileCreateDto input)
{
string fileSystemPath = GetFileSystemPath(input.Path);
fileSystemPath = Path.Combine(fileSystemPath, input.FileName);
var blobName = GetFileSystemRelativePath(fileSystemPath);
// 去除第一个路径标识符
blobName = blobName.RemovePreFix("/", "\\");
if (!input.Rewrite && await BlobContainer.ExistsAsync(blobName))
{
throw new UserFriendlyException(L["FilePathAlreadyExists"]);
}
await BlobContainer.SaveAsync(blobName, input.Data, input.Rewrite);
Array.Clear(input.Data, 0, input.Data.Length);
}
[Authorize(AbpFileManagementPermissions.FileSystem.Create)]
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(L["PathAlreadyExists"]);
}
Directory.CreateDirectory(newFloderPath);
return Task.CompletedTask;
}
[Authorize(AbpFileManagementPermissions.FileSystem.FileManager.Delete)]
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;
}
[Authorize(AbpFileManagementPermissions.FileSystem.Delete)]
public virtual Task DeleteFolderAsync([Required, StringLength(255)] string path)
{
string fileSystemPath = GetFileSystemPath(path);
if (!Directory.Exists(fileSystemPath))
{
throw new UserFriendlyException(L["FilePathNotFound"]);
}
var fileSystemChildrenPath = Directory.GetDirectories(fileSystemPath);
if (fileSystemChildrenPath.Length > 0)
{
throw new UserFriendlyException(L["PathCannotBeDeletedWithNotEmpty"]);
}
var fileSystemPathFiles = Directory.GetFiles(fileSystemPath);
if (fileSystemPathFiles.Length > 0)
{
throw new UserFriendlyException(L["PathCannotBeDeletedWithNotEmpty"]);
}
Directory.Delete(fileSystemPath);
return Task.CompletedTask;
}
[Authorize(AbpFileManagementPermissions.FileSystem.FileManager.Download)]
public virtual async Task<Stream> DownloadFileAsync(FileSystemGetDto input)
{
var fileSystemPath = GetFileSystemPath(input.Path);
fileSystemPath = Path.Combine(fileSystemPath, input.Name);
var blobName = GetFileSystemRelativePath(fileSystemPath);
// 去除第一个路径标识符
blobName = blobName.RemovePreFix("/", "\\");
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,
Extension = fileInfo.Extension,
CreationTime = fileInfo.CreationTime,
LastModificationTime = fileInfo.LastWriteTime
};
if (fileInfo.Directory != null && !fileInfo.Directory.FullName.IsNullOrWhiteSpace())
{
fileSystem.Parent = GetFileSystemRelativePath(fileInfo.Directory.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.FullName.IsNullOrWhiteSpace())
{
fileSystem.Parent = GetFileSystemRelativePath(directoryInfo.Parent.FullName);
}
return Task.FromResult(fileSystem);
}
throw new UserFriendlyException(L["FilePathNotFound"]);
}
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);
if (!directoryInfo.Exists)
{
return Task.FromResult(new PagedResultDto<FileSystemDto>(0, fileSystems));
}
// 查询全部文件系统
var fileSystemInfos = directoryInfo.GetFileSystemInfos();
// 指定搜索条件查询目录
FileSystemInfo[] fileSystemInfoSearchChildren;
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;
fileSystem.Extension = fileInfo.Extension;
if (fileInfo.Directory != null && !fileInfo.Directory.FullName.IsNullOrWhiteSpace())
{
fileSystem.Parent = GetFileSystemRelativePath(fileInfo.Directory.FullName);
}
}
else if (fileSystemInfo is DirectoryInfo directory)
{
fileSystem.Type = FileSystemType.Folder;
if (directory.Parent != null && !directory.Parent.FullName.IsNullOrWhiteSpace())
{
fileSystem.Parent = GetFileSystemRelativePath(directory.Parent.FullName);
}
}
fileSystems.Add(fileSystem);
}
fileSystems = fileSystems
.OrderBy(f => f.Type)
.ThenBy(f => f.Name)
.ToList();
return Task.FromResult(new PagedResultDto<FileSystemDto>(
fileSystemInfos.Length, fileSystems
));
}
[Authorize(AbpFileManagementPermissions.FileSystem.FileManager.Move)]
public virtual Task MoveFileAsync(FileCopyOrMoveDto input)
{
string fileSystemPath = GetFileSystemPath(input.Path);
fileSystemPath = Path.Combine(fileSystemPath, input.Name);
if (!File.Exists(fileSystemPath))
{
throw new UserFriendlyException(L["FilePathNotFound"]);
}
var moveToFilePath = GetFileSystemPath(input.ToPath);
moveToFilePath = Path.Combine(moveToFilePath, input.ToName ?? input.Name);
if (File.Exists(moveToFilePath))
{
throw new UserFriendlyException(L["FilePathAlreadyExists"]);
}
File.Move(fileSystemPath, moveToFilePath);
return Task.CompletedTask;
}
[Authorize(AbpFileManagementPermissions.FileSystem.Move)]
public virtual Task MoveFolderAsync([Required, StringLength(255)] string path, FolderMoveDto input)
{
string fileSystemPath = GetFileSystemPath(path);
if (!Directory.Exists(fileSystemPath))
{
throw new UserFriendlyException(L["FilePathNotFound"]);
}
var moveToFilePath = GetFileSystemPath(input.MoveToPath);
if (Directory.Exists(moveToFilePath))
{
throw new UserFriendlyException(L["FilePathAlreadyExists"]);
}
Directory.Move(fileSystemPath, moveToFilePath);
return Task.CompletedTask;
}
[Authorize(AbpFileManagementPermissions.FileSystem.Update)]
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(L["FilePathAlreadyExists"]);
}
File.Move(fileSystemPath, renameFilePath);
var fileInfo = new FileInfo(renameFilePath);
var fileSystem = new FileSystemDto
{
Type = FileSystemType.File,
Name = fileInfo.Name,
Size = fileInfo.Length,
Extension = fileInfo.Extension,
CreationTime = fileInfo.CreationTime,
LastModificationTime = fileInfo.LastWriteTime
};
if (fileInfo.Directory != null && !fileInfo.Directory.FullName.IsNullOrWhiteSpace())
{
fileSystem.Parent = GetFileSystemRelativePath(fileInfo.Directory.FullName);
}
return Task.FromResult(fileSystem);
}
if (Directory.Exists(fileSystemPath))
{
if (Directory.Exists(renameFilePath))
{
throw new UserFriendlyException(L["FilePathAlreadyExists"]);
}
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.FullName.IsNullOrWhiteSpace())
{
fileSystem.Parent = GetFileSystemRelativePath(directoryInfo.Parent.FullName);
}
return Task.FromResult(fileSystem);
}
throw new UserFriendlyException(L["FilePathNotFound"]);
}
/// <summary>
/// 获取文件系统相对路径
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
protected virtual string GetFileSystemRelativePath(string path)
{
// 去除完整路径中的文件系统根目录
var fileSystemConfiguration = GetFileSystemBlobProviderConfiguration();
var blobPath = fileSystemConfiguration.BasePath;
// 去除租户或宿主目录
if (CurrentTenant.Id == null)
{
blobPath = Path.Combine(blobPath, "host");
}
else
{
blobPath = Path.Combine(blobPath, "tenants", CurrentTenant.Id.Value.ToString("D"));
}
// 去除完整路径中的容器根目录
var containerName = BlobContainerNameAttribute.GetContainerName<AbpFileManagementContainer>();
if (path.Contains(containerName))
{
blobPath = Path.Combine(blobPath, containerName);
}
path = path.Replace(blobPath, "");
path = path.Replace('/', Path.DirectorySeparatorChar);
path = path.Replace('\\', Path.DirectorySeparatorChar);
return path;
}
/// <summary>
/// 获取合并的文件路径
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
protected virtual string GetFileSystemPath(string path)
{
var fileSystemConfiguration = GetFileSystemBlobProviderConfiguration();
var blobPath = GetFileSystemBashPath();
if (!path.IsNullOrWhiteSpace() && fileSystemConfiguration.AppendContainerNameToBasePath)
{
path = path.Replace('/', Path.DirectorySeparatorChar);
path = path.Replace('\\', Path.DirectorySeparatorChar);
// 去除第一个路径标识符
path = path.RemovePreFix("/", "\\");
blobPath = Path.Combine(blobPath, path);
}
return blobPath;
}
/// <summary>
/// 获取文件系统存储路径
/// </summary>
/// <returns></returns>
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"));
}
var containerName = BlobContainerNameAttribute.GetContainerName<AbpFileManagementContainer>();
blobPath = Path.Combine(blobPath, containerName);
if (!Directory.Exists(blobPath))
{
Directory.CreateDirectory(blobPath);
}
return blobPath;
}
protected virtual FileSystemBlobProviderConfiguration GetFileSystemBlobProviderConfiguration()
{
var blobConfiguration = BlobContainerConfigurationProvider
.Get<AbpFileManagementContainer>();
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);
}
}
}
}
}

8
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain.Shared/LINGYUN/Abp/FileManagement/FileManagementErrorCodes.cs

@ -1,8 +1,4 @@
using System; namespace LINGYUN.Abp.FileManagement
using System.Collections.Generic;
using System.Text;
namespace LINGYUN.Abp.FileManagement
{ {
public static class FileManagementErrorCodes public static class FileManagementErrorCodes
{ {
@ -15,5 +11,7 @@ namespace LINGYUN.Abp.FileManagement
public const string ObjectDeleteWithNotEmpty = Namespace + ":020001"; public const string ObjectDeleteWithNotEmpty = Namespace + ":020001";
public const string ObjectAlreadyExists = Namespace + ":020402"; public const string ObjectAlreadyExists = Namespace + ":020402";
public const string ObjectNotFound = Namespace + ":020404"; public const string ObjectNotFound = Namespace + ":020404";
public const string OssNameHasTooLong = Namespace + ":000405";
} }
} }

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

@ -7,6 +7,7 @@
"Abp.FileManagement:020001": "An object that has more than one child cannot be deleted!", "Abp.FileManagement:020001": "An object that has more than one child cannot be deleted!",
"Abp.FileManagement:020402": "The object name already exists!", "Abp.FileManagement:020402": "The object name already exists!",
"Abp.FileManagement:020404": "The queried object could not be found!", "Abp.FileManagement:020404": "The queried object could not be found!",
"Abp.FileManagement:000405": "The path object name has exceeded the allowable maximum length and cannot continue to create a new object!",
"Permission:FileManagement": "File management", "Permission:FileManagement": "File management",
"Permission:FileSystem": "File system", "Permission:FileSystem": "File system",
"Permission:FileManager": "Files", "Permission:FileManager": "Files",

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

@ -7,6 +7,7 @@
"Abp.FileManagement:020001": "不能删除存在多个子级的对象!", "Abp.FileManagement:020001": "不能删除存在多个子级的对象!",
"Abp.FileManagement:020402": "对象名称已经存在!", "Abp.FileManagement:020402": "对象名称已经存在!",
"Abp.FileManagement:020404": "未能找到查询的对象!", "Abp.FileManagement:020404": "未能找到查询的对象!",
"Abp.FileManagement:000405": "此路径对象名称已超出允许的最大长度,无法继续创建新对象!",
"Permission:FileManagement": "文件管理", "Permission:FileManagement": "文件管理",
"Permission:FileSystem": "文件系统", "Permission:FileSystem": "文件系统",
"Permission:FileManager": "文件", "Permission:FileManager": "文件",

2
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.Domain/LINGYUN.Abp.FileManagement.Domain.csproj

@ -8,7 +8,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.BlobStoring.FileSystem" Version="4.2.1" /> <PackageReference Include="Volo.Abp.BlobStoring" Version="4.2.1" />
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="4.2.1" /> <PackageReference Include="Volo.Abp.Ddd.Domain" Version="4.2.1" />
</ItemGroup> </ItemGroup>

61
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.FileSystem/LINGYUN/Abp/FileManagement/FileSystem/FileSystemOssContainer.cs

@ -1,16 +1,16 @@
using System; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
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.BlobStoring; using Volo.Abp.BlobStoring;
using Volo.Abp.BlobStoring.FileSystem; using Volo.Abp.BlobStoring.FileSystem;
using Volo.Abp.MultiTenancy;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.IO; using Volo.Abp.IO;
using Volo.Abp; using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.FileManagement.FileSystem namespace LINGYUN.Abp.FileManagement.FileSystem
{ {
@ -44,11 +44,23 @@ namespace LINGYUN.Abp.FileManagement.FileSystem
public virtual Task BulkDeleteObjectsAsync(BulkDeleteObjectRequest request) public virtual Task BulkDeleteObjectsAsync(BulkDeleteObjectRequest request)
{ {
var filesPath = request.Objects.Select(x => CalculateFilePath(request.Bucket, x)); var objectPath = !request.Path.IsNullOrWhiteSpace()
? request.Path.EnsureEndsWith('/')
: "";
var filesPath = request.Objects.Select(x => CalculateFilePath(request.Bucket, objectPath + x));
foreach (var file in filesPath) foreach (var file in filesPath)
{ {
if (File.Exists(file)) if (Directory.Exists(file))
{
if (Directory.GetFileSystemEntries(file).Length > 0)
{
throw new BusinessException(code: FileManagementErrorCodes.ContainerDeleteWithNotEmpty);
// throw new ContainerDeleteWithNotEmptyException("00101", $"Can't not delete container {name}, because it is not empty!");
}
Directory.Delete(file);
}
else if (File.Exists(file))
{ {
File.Delete(file); File.Delete(file);
} }
@ -60,6 +72,7 @@ namespace LINGYUN.Abp.FileManagement.FileSystem
public virtual Task<OssContainer> CreateAsync(string name) public virtual Task<OssContainer> CreateAsync(string name)
{ {
var filePath = CalculateFilePath(name); var filePath = CalculateFilePath(name);
ThrowOfPathHasTooLong(filePath);
if (!Directory.Exists(filePath)) if (!Directory.Exists(filePath))
{ {
Directory.CreateDirectory(filePath); Directory.CreateDirectory(filePath);
@ -91,6 +104,8 @@ namespace LINGYUN.Abp.FileManagement.FileSystem
var filePath = CalculateFilePath(request.Bucket, objectName); var filePath = CalculateFilePath(request.Bucket, objectName);
if (!request.Content.IsNullOrEmpty()) if (!request.Content.IsNullOrEmpty())
{ {
ThrowOfPathHasTooLong(filePath);
if (File.Exists(filePath)) if (File.Exists(filePath))
{ {
throw new BusinessException(code: FileManagementErrorCodes.ObjectAlreadyExists); throw new BusinessException(code: FileManagementErrorCodes.ObjectAlreadyExists);
@ -126,6 +141,7 @@ namespace LINGYUN.Abp.FileManagement.FileSystem
} }
else else
{ {
ThrowOfPathHasTooLong(filePath);
if (Directory.Exists(filePath)) if (Directory.Exists(filePath))
{ {
throw new BusinessException(code: FileManagementErrorCodes.ObjectAlreadyExists); throw new BusinessException(code: FileManagementErrorCodes.ObjectAlreadyExists);
@ -159,14 +175,15 @@ namespace LINGYUN.Abp.FileManagement.FileSystem
var filePath = CalculateFilePath(name); var filePath = CalculateFilePath(name);
if (!Directory.Exists(filePath)) if (!Directory.Exists(filePath))
{ {
// 非空目录无法删除 throw new BusinessException(code: FileManagementErrorCodes.ContainerNotFound);
if (Directory.GetFiles(filePath).Length > 0)
{
throw new BusinessException(code: FileManagementErrorCodes.ContainerDeleteWithNotEmpty);
// throw new ContainerDeleteWithNotEmptyException("00101", $"Can't not delete container {name}, because it is not empty!");
}
Directory.Delete(filePath);
} }
// 非空目录无法删除
if (Directory.GetFileSystemEntries(filePath).Length > 0)
{
throw new BusinessException(code: FileManagementErrorCodes.ContainerDeleteWithNotEmpty);
// throw new ContainerDeleteWithNotEmptyException("00101", $"Can't not delete container {name}, because it is not empty!");
}
Directory.Delete(filePath);
return Task.CompletedTask; return Task.CompletedTask;
} }
@ -177,13 +194,13 @@ namespace LINGYUN.Abp.FileManagement.FileSystem
? request.Object ? request.Object
: request.Path.EnsureEndsWith('/') + request.Object; : request.Path.EnsureEndsWith('/') + request.Object;
var filePath = CalculateFilePath(request.Bucket, objectName); var filePath = CalculateFilePath(request.Bucket, objectName);
if (!File.Exists(filePath)) if (File.Exists(filePath))
{ {
File.Delete(filePath); File.Delete(filePath);
} }
else if (Directory.Exists(filePath)) else if (Directory.Exists(filePath))
{ {
if (Directory.GetFiles(filePath).Length > 0) if (Directory.GetFileSystemEntries(filePath).Length > 0)
{ {
throw new BusinessException(code: FileManagementErrorCodes.ObjectDeleteWithNotEmpty); throw new BusinessException(code: FileManagementErrorCodes.ObjectDeleteWithNotEmpty);
} }
@ -508,5 +525,15 @@ namespace LINGYUN.Abp.FileManagement.FileSystem
return blobPath; return blobPath;
} }
private void ThrowOfPathHasTooLong(string path)
{
// Windows 133 260
// Linux 255 4096
//if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && path.Length >= 255) // 预留5位
//{
// throw new BusinessException(code: FileManagementErrorCodes.OssNameHasTooLong);
//}
}
} }
} }

265
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN/Abp/FileManagement/FileSystemController.cs

@ -1,265 +0,0 @@
using LINGYUN.Abp.FileManagement.Localization;
using LINGYUN.Abp.FileManagement.Permissions;
using LINGYUN.Abp.FileManagement.Settings;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
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;
using Volo.Abp.Features;
using LINGYUN.Abp.FileManagement.Features;
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;
LocalizationResource = typeof(AbpFileManagementResource);
}
[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")]
[RequiresFeature(AbpFileManagementFeatureNames.FileSystem.UploadFile)]
[Authorize(AbpFileManagementPermissions.FileSystem.FileManager.Create)]
public virtual async Task CreateFileAsync([FromForm] FileUploadDto input)
{
// 检查文件大小
var fileSizeLimited = await SettingProvider
.GetAsync(
AbpFileManagementSettingNames.FileLimitLength,
AbpFileManagementSettingNames.DefaultFileLimitLength);
if (fileSizeLimited * 1024 * 1024 < input.TotalSize)
{
throw new UserFriendlyException(L["UploadFileSizeBeyondLimit", fileSizeLimited]);
}
// 采用分块模式上传文件
// 保存分块到临时目录
var fileName = input.FileName;
// 文件扩展名
var fileExtensionName = FileHelper.GetExtension(fileName);
var fileAllowExtension = await SettingProvider
.GetOrDefaultAsync(AbpFileManagementSettingNames.AllowFileExtensions, ServiceProvider);
// 检查文件扩展名
if (!fileAllowExtension.Split(',')
.Any(fe => fe.Equals(fileExtensionName, StringComparison.CurrentCultureIgnoreCase)))
{
throw new UserFriendlyException(L["NotAllowedFileExtensionName", fileExtensionName]);
}
// 以上传的文件名创建一个临时目录
var tempFilePath = Path.Combine(
Path.GetTempPath(),
"lingyun-abp-file-management",
"upload",
string.Concat(input.Path ?? "", input.FileName).ToMd5());
DirectoryHelper.CreateIfNotExists(tempFilePath);
// 以上传的分片索引创建临时文件
var tempSavedFile = Path.Combine(tempFilePath, $"{input.ChunkNumber}.{fileExtensionName}");
try
{
if (HttpContext.RequestAborted.IsCancellationRequested)
{
// 如果取消请求,删除临时目录
Directory.Delete(tempFilePath, true);
return;
}
if (input.File != null)
{
// 保存临时文件
using (var fs = new FileStream(tempSavedFile, FileMode.Create, FileAccess.Write))
{
// 写入当前分片文件
await input.File.CopyToAsync(fs);
}
}
if (input.ChunkNumber == input.TotalChunks)
{
// 合并文件
var mergeSavedFile = Path.Combine(tempFilePath, $"{fileName}");
// 获取并排序所有分片文件
var mergeFiles = Directory.GetFiles(tempFilePath).OrderBy(f => f.Length).ThenBy(f => f);
// 创建临时合并文件
input.Data = new byte[0];
foreach (var mergeFile in mergeFiles)
{
// 读取当前文件字节
var mergeFileBytes = await FileHelper.ReadAllBytesAsync(mergeFile);
// 写入到合并文件流
input.Data = input.Data.Concat(mergeFileBytes).ToArray();
Array.Clear(mergeFileBytes,0, mergeFileBytes.Length);
// 删除已参与合并的临时文件分片
FileHelper.DeleteIfExists(mergeFile);
}
await FileSystemAppService.CreateFileAsync(input);
// 文件保存之后删除临时文件目录
Directory.Delete(tempFilePath, true);
}
}
catch
{
// 发生异常删除临时文件目录
Directory.Delete(tempFilePath, true);
throw;
}
}
[HttpPost]
[Route("folders")]
public virtual async Task CreateFolderAsync(FolderCreateDto input)
{
await FileSystemAppService.CreateFolderAsync(input);
}
[HttpDelete]
[Route("files")]
public virtual async Task DeleteFileAsync(FileDeleteDto input)
{
await FileSystemAppService.DeleteFileAsync(input);
}
[HttpDelete]
[Route("folders")]
public virtual async Task DeleteFolderAsync([Required, StringLength(255)] string path)
{
await FileSystemAppService.DeleteFolderAsync(path);
}
[HttpGet]
[Route("files")]
[RequiresFeature(AbpFileManagementFeatureNames.FileSystem.DownloadFile)]
[Authorize(AbpFileManagementPermissions.FileSystem.FileManager.Download)]
public virtual async Task<IActionResult> DownloadFileAsync(FileSystemDownloadDto input)
{
var tempFileName = string.Concat(input.Path ?? "", input.Name);
tempFileName = tempFileName.ToMd5() + Path.GetExtension(input.Name);
// 以上传的文件名创建一个临时目录
var tempFilePath = Path.Combine(
Path.GetTempPath(),
"lingyun-abp-file-management",
"download");
DirectoryHelper.CreateIfNotExists(tempFilePath);
tempFilePath = Path.Combine(tempFilePath, tempFileName);
long contentLength = 0L;
// 单个分块大小 2MB
int bufferSize = 2 * 1024 * 1024;
using (new DisposeAction(() =>
{
// 最终下载完毕后,删除临时文件
if (bufferSize + input.CurrentByte > contentLength)
{
FileHelper.DeleteIfExists(tempFilePath);
}
}))
{
if (!System.IO.File.Exists(tempFilePath))
{
var blobStream = await FileSystemAppService.DownloadFileAsync(input);
using (var tempFileStream = new FileStream(tempFilePath, FileMode.Create, FileAccess.Write))
{
blobStream.Position = 0;
await blobStream.CopyToAsync(tempFileStream);
}
}
// 读取缓存文件
using var fileStream = new FileStream(tempFilePath, FileMode.Open, FileAccess.Read);
// 得到文件扩展名
var fileExt = Path.GetExtension(input.Name);
var provider = new FileExtensionContentTypeProvider();
// Http响应标头的文件类型
string memi = provider.Mappings[fileExt];
// 文件大小
contentLength = fileStream.Length;
if (bufferSize > contentLength)
{
var currentTransferBytes = await fileStream.GetAllBytesAsync();
// 写入响应流
return File(currentTransferBytes, memi, input.Name);
}
else
{
// 当前分页传输字节
byte[] currentTransferBytes = new byte[bufferSize];
if (input.CurrentByte + bufferSize >= contentLength)
{
currentTransferBytes = new byte[contentLength - input.CurrentByte];
}
// 读取文件流中的当前分块区段
fileStream.Seek(input.CurrentByte, SeekOrigin.Begin);
await fileStream.ReadAsync(currentTransferBytes, 0, currentTransferBytes.Length);
// 写入响应流
return File(currentTransferBytes, memi, input.Name);
}
}
}
[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);
}
}
}

35
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN/Abp/FileManagement/FileUploadDto.cs

@ -1,35 +0,0 @@
using Microsoft.AspNetCore.Http;
using System.ComponentModel.DataAnnotations;
namespace LINGYUN.Abp.FileManagement
{
public class FileUploadDto : FileCreateDto
{
/// <summary>
/// 常规块大小
/// </summary>
[Required]
public int ChunkSize { get; set; }
/// <summary>
/// 当前块大小
/// </summary>
[Required]
public int CurrentChunkSize { get; set; }
/// <summary>
/// 当前上传中块的索引
/// </summary>
[Required]
public int ChunkNumber { get; set; }
/// <summary>
/// 块总数
/// </summary>
[Required]
public int TotalChunks { get; set; }
/// <summary>
/// 总文件大小
/// </summary>
[Required]
public int TotalSize { get; set; }
public IFormFile File { get; set; }
}
}

96
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN/Abp/FileManagement/FileValidater.cs

@ -0,0 +1,96 @@
using LINGYUN.Abp.FileManagement.Settings;
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
using Volo.Abp.IO;
using Volo.Abp.Settings;
using Microsoft.Extensions.Localization;
using LINGYUN.Abp.FileManagement.Localization;
namespace LINGYUN.Abp.FileManagement
{
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<AbpFileManagementResource> 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(
AbpFileManagementSettingNames.FileLimitLength,
AbpFileManagementSettingNames.DefaultFileLimitLength);
var fileAllowExtension = await _settingProvider
.GetOrDefaultAsync(AbpFileManagementSettingNames.AllowFileExtensions, _serviceProvider);
return new FileValidation(fileSizeLimited, fileAllowExtension.Split(','));
}
}
public class FileValidation
{
public const string CacheKey = "Abp.FileManagement.FileValidation";
public int SizeLimit { get; set; }
public string[] AllowedExtensions { get; set; }
public FileValidation()
{
}
public FileValidation(
int sizeLimit,
string[] allowedExtensions)
{
SizeLimit = sizeLimit;
AllowedExtensions = allowedExtensions;
}
}
}

9
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN/Abp/FileManagement/IFileValidater.cs

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

96
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN/Abp/FileManagement/OssObjectController.cs

@ -1,9 +1,16 @@
using Microsoft.AspNetCore.Mvc; using LINGYUN.Abp.FileManagement.Settings;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Auditing;
using Volo.Abp.IO;
using Volo.Abp.Settings;
using Volo.Abp.Validation; using Volo.Abp.Validation;
namespace LINGYUN.Abp.FileManagement namespace LINGYUN.Abp.FileManagement
@ -13,11 +20,14 @@ namespace LINGYUN.Abp.FileManagement
[Route("api/file-management/objects")] [Route("api/file-management/objects")]
public class OssObjectController : AbpController, IOssObjectAppService public class OssObjectController : AbpController, IOssObjectAppService
{ {
protected IFileValidater FileValidater { get; }
protected IOssObjectAppService OssObjectAppService { get; } protected IOssObjectAppService OssObjectAppService { get; }
public OssObjectController( public OssObjectController(
IFileValidater fileValidater,
IOssObjectAppService ossObjectAppService) IOssObjectAppService ossObjectAppService)
{ {
FileValidater = fileValidater;
OssObjectAppService = ossObjectAppService; OssObjectAppService = ossObjectAppService;
} }
@ -29,30 +39,82 @@ namespace LINGYUN.Abp.FileManagement
[HttpPost] [HttpPost]
[Route("upload")] [Route("upload")]
public virtual async Task<OssObjectDto> UploadAsync([FromForm] UploadOssObjectInput input) [DisableAuditing]
public virtual async Task UploadAsync([FromForm] UploadOssObjectInput input)
{ {
var createOssObjectInput = new CreateOssObjectInput await FileValidater.ValidationAsync(input);
// 以上传的文件名创建一个临时目录
var tempFilePath = Path.Combine(
Path.GetTempPath(),
"lingyun-abp-application",
"upload-tmp",
string.Concat(input.Path ?? "", input.FileName).ToMd5());
DirectoryHelper.CreateIfNotExists(tempFilePath);
// 以上传的分片索引创建临时文件
var tempSavedFile = Path.Combine(tempFilePath, $"{input.ChunkNumber}.uploadtmp");
try
{ {
Bucket = input.Bucket, if (HttpContext.RequestAborted.IsCancellationRequested)
Path = input.Path, {
Object = input.Name // 如果取消请求,删除临时目录
}; Directory.Delete(tempFilePath, true);
if (input.File != null) return;
}
if (input.File != null)
{
// 保存临时文件
using (var fs = new FileStream(tempSavedFile, FileMode.Create, FileAccess.Write))
{
// 写入当前分片文件
await input.File.CopyToAsync(fs);
}
}
if (input.ChunkNumber == input.TotalChunks)
{
var createOssObjectInput = new CreateOssObjectInput
{
Bucket = input.Bucket,
Path = input.Path,
Object = input.FileName
};
// 合并文件
var mergeSavedFile = Path.Combine(tempFilePath, $"{input.FileName}");
// 获取并排序所有分片文件
var mergeFiles = Directory.GetFiles(tempFilePath).OrderBy(f => f.Length).ThenBy(f => f);
// 创建临时合并文件
using (var memoryStream = new MemoryStream())
{
foreach (var mergeFile in mergeFiles)
{
// 读取当前文件字节
var mergeFileBytes = await FileHelper.ReadAllBytesAsync(mergeFile);
// 写入到合并文件流
await memoryStream.WriteAsync(mergeFileBytes, HttpContext.RequestAborted);
Array.Clear(mergeFileBytes, 0, mergeFileBytes.Length);
// 删除已参与合并的临时文件分片
FileHelper.DeleteIfExists(mergeFile);
}
createOssObjectInput.SetContent(memoryStream);
await OssObjectAppService.CreateAsync(createOssObjectInput);
// 文件保存之后删除临时文件目录
Directory.Delete(tempFilePath, true);
}
}
}
catch
{ {
//if (input.File.Length <= 0) // 发生异常删除临时文件目录
//{ Directory.Delete(tempFilePath, true);
// ThrowValidationException(L["FileNotBeNullOrEmpty"], "File"); throw;
//}
createOssObjectInput.Object = input.File.FileName;
createOssObjectInput.Content = input.File.OpenReadStream();
} }
return await OssObjectAppService.CreateAsync(createOssObjectInput);
} }
[HttpDelete] [HttpDelete]
[Route("bulk-delete")] [Route("bulk-delete")]
public virtual async Task BulkDeleteAsync(BulkDeleteOssObjectInput input) public virtual async Task BulkDeleteAsync([FromBody] BulkDeleteOssObjectInput input)
{ {
await OssObjectAppService.BulkDeleteAsync(input); await OssObjectAppService.BulkDeleteAsync(input);
} }

37
aspnet-core/modules/file-management/LINGYUN.Abp.FileManagement.HttpApi/LINGYUN/Abp/FileManagement/UploadOssObjectInput.cs

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using System.ComponentModel.DataAnnotations;
namespace LINGYUN.Abp.FileManagement namespace LINGYUN.Abp.FileManagement
{ {
@ -6,7 +7,41 @@ namespace LINGYUN.Abp.FileManagement
{ {
public string Bucket { get; set; } public string Bucket { get; set; }
public string Path { get; set; } public string Path { get; set; }
public string Name { get; set; }
#region 配合Uplaoder 分块传输
/// <summary>
/// 文件名
/// </summary>
[Required]
public string FileName { get; set; }
/// <summary>
/// 常规块大小
/// </summary>
[Required]
public int ChunkSize { get; set; }
/// <summary>
/// 当前块大小
/// </summary>
[Required]
public int CurrentChunkSize { get; set; }
/// <summary>
/// 当前上传中块的索引
/// </summary>
[Required]
public int ChunkNumber { get; set; }
/// <summary>
/// 块总数
/// </summary>
[Required]
public int TotalChunks { get; set; }
/// <summary>
/// 总文件大小
/// </summary>
[Required]
public int TotalSize { get; set; }
#endregion
public IFormFile File { get; set; } public IFormFile File { get; set; }
} }
} }

52
vueJs/src/api/oss-manager.ts

@ -5,7 +5,7 @@ import { urlStringify } from '@/utils/index'
const serviceUrl = process.env.VUE_APP_BASE_API const serviceUrl = process.env.VUE_APP_BASE_API
const containerUrl = '/api/file-management/containes' const containerUrl = '/api/file-management/containes'
const objectUrl = '/api/file-management/objects' const objectUrl = '/api/file-management/objects'
export const objectUploadUrl = objectUrl + '/upload' export const objectUploadUrl = serviceUrl + objectUrl + '/upload'
export const staticUrl = '/api/files/static/' export const staticUrl = '/api/files/static/'
export default class OssManager { export default class OssManager {
@ -29,7 +29,7 @@ export default class OssManager {
return ApiService.Delete(_url, serviceUrl) return ApiService.Delete(_url, serviceUrl)
} }
public static createFolder(bucket: string, name: string, path: string = "") { public static createFolder(bucket: string, name: string, path: string = '') {
const input = { const input = {
bucket: bucket, bucket: bucket,
object: name, object: name,
@ -43,7 +43,7 @@ export default class OssManager {
return ApiService.Get<OssObjectResultList>(_url, serviceUrl) return ApiService.Get<OssObjectResultList>(_url, serviceUrl)
} }
public static getObject(bucket: string, object: string, path: string = "") { public static getObject(bucket: string, object: string, path: string = '') {
let _url = objectUrl + '?bucket=' + bucket + '&object=' + object let _url = objectUrl + '?bucket=' + bucket + '&object=' + object
if (path) { if (path) {
_url += '&path=' + path _url += '&path=' + path
@ -51,31 +51,53 @@ export default class OssManager {
return ApiService.Get<OssObject>(_url, serviceUrl) return ApiService.Get<OssObject>(_url, serviceUrl)
} }
public static getObjectData(bucket: string, object: string, path: string = "") { public static getObjectData(bucket: string, object: string, path: string = '') {
let _url = staticUrl + bucket + '/'
if (path) {
// 某些情况下要对 / 编码
_url += '/p/' + path.replace('/', '%2F')
if (_url.endsWith('%2F')) {
_url = _url.substring(0, _url.length - 3) + '/'
}
}
_url += object
return ApiService.HttpRequest<Blob>({ return ApiService.HttpRequest<Blob>({
url: _url, url: this.generateOssUrl(bucket, object, path),
baseURL: serviceUrl, baseURL: serviceUrl,
method: 'GET', method: 'GET',
responseType: 'blob' responseType: 'blob'
}) })
} }
public static deleteObject(bucket: string, object: string, path: string = "") { public static deleteObject(bucket: string, object: string, path: string = '') {
let _url = objectUrl + '?bucket=' + bucket + '&object=' + object let _url = objectUrl + '?bucket=' + bucket + '&object=' + object
if (path) { if (path) {
_url += '&path=' + path _url += '&path=' + path
} }
return ApiService.Delete(_url, serviceUrl) return ApiService.Delete(_url, serviceUrl)
} }
public static bulkDeleteObject(bucket: string, objects: string[], path: string = '') {
const _url = objectUrl + '/bulk-delete'
return ApiService
.HttpRequest({
url: _url,
baseURL: serviceUrl,
method: 'DELETE',
data: {
bucket: bucket,
path: path,
objects: objects
}
})
}
public static generateOssUrl(bucket: string, object: string, path: string = '', prefix: string = '') {
let _url = staticUrl + bucket + '/'
if (path) {
// 某些情况下要对 / 编码
_url += '/p/' + path.replace('/', '%2F')
if (_url.endsWith('%2F')) {
_url = _url.substring(0, _url.length - 3) + '/'
}
}
_url += object
if (prefix) {
_url = prefix + _url
}
return _url
}
} }
export class GetOssContainerRequest extends PagedAndSortedResultRequestDto { export class GetOssContainerRequest extends PagedAndSortedResultRequestDto {

131
vueJs/src/views/oss-management/components/OssObjectUploadDialog.vue

@ -0,0 +1,131 @@
<template>
<el-dialog
:title="$t('fileSystem.upload')"
:visible="showDialog"
custom-class="modal-form"
@close="onFormClosed"
>
<uploader
ref="uploader"
:options="options"
:auto-start="false"
class="uploader-pane"
@file-added="onFileAdded"
@file-error="onFileError"
@file-complete="onFileUploadCompleted"
>
<uploader-unsupport />
<uploader-drop>
<uploader-btn :attrs="attrs">
{{ $t('fileSystem.addFile') }}
</uploader-btn>
</uploader-drop>
<uploader-list />
</uploader>
</el-dialog>
</template>
<script lang="ts">
import { Component, Vue, Prop, Watch } from 'vue-property-decorator'
import { objectUploadUrl } from '@/api/oss-manager'
import { UserModule } from '@/store/modules/user'
export class UploadOptions {
target!: string
chunkSize!: number
testChunks!: boolean
fileParameterName!: string
maxChunkRetries!: number
headers?: any
query?: any
permanentErrors?: number[]
successStatuses?: number[]
constructor() {
this.query = {}
this.headers = {}
this.testChunks = false
this.successStatuses = new Array<number>()
this.permanentErrors = new Array<number>()
}
}
@Component({
name: 'OssObjectUploadDialog'
})
export default class extends Vue {
@Prop({ default: () => new UploadOptions() })
private options!: UploadOptions
@Prop({ default: '' })
private bucket!: string
@Prop({ default: '' })
private path!: string
@Prop({ default: false })
private showDialog!: boolean
private attrs!: {[key: string]: any}
private files?: any = {}
constructor() {
super()
this.attrs = {
accept: ['image/*', 'document/*', 'video/*', 'audio/*']
}
this.options.target = objectUploadUrl
this.options.successStatuses = [200, 201, 202, 204, 205]
this.options.permanentErrors = [400, 401, 403, 404, 415, 500, 501]
this.options.headers.Authorization = UserModule.token
}
public close() {
this.files = {}
const uploadControl = this.$refs.uploader as any
uploadControl.files = []
uploadControl.fileList = []
uploadControl.uploader.cancel()
}
@Watch('bucket', { immediate: true })
private onBucketChanged() {
this.options.query.bucket = this.bucket
}
@Watch('path', { immediate: true })
private onPathChanged() {
this.options.query.path = this.path
}
private onFileAdded(file: any) {
this.files[file.name] = file.chunkSize
file.uploader.fileStatusText.error = this.$t('fileSystem.uploadError')
file.uploader.fileStatusText.paused = this.$t('fileSystem.paused')
file.uploader.fileStatusText.success = this.$t('fileSystem.uploadSuccess')
file.uploader.fileStatusText.waiting = this.$t('fileSystem.waitingUpload')
file.uploader.fileStatusText.uploading = this.$t('fileSystem.uploading')
}
private onFileError(rootFile: any, file: any, message: any) {
const abpResponse = JSON.parse(message)
this.$message.error(abpResponse.error.message)
}
private onFileUploadCompleted(file: any) {
const uploadControl = this.$refs.uploader as any
if (uploadControl && uploadControl.uploader) {
uploadControl.uploader.removeFile(file)
}
this.$emit('onFileUploaded', file.name)
}
private onFormClosed() {
this.$emit('closed')
}
}
</script>
<style lang="scss" scoped>
</style>

78
vueJs/src/views/oss-management/index.vue

@ -157,6 +157,15 @@
:path="selectionOssObject.path" :path="selectionOssObject.path"
@closed="showOssObject=false" @closed="showOssObject=false"
/> />
<OssObjectUploadDialog
ref="ossObjectUploadDialog"
:show-dialog="showUploadOss"
:bucket="bucket"
:path="uploadPath"
@closed="showUploadOss=false"
@onFileUploaded="onFileUploaded"
/>
</div> </div>
</template> </template>
@ -171,6 +180,7 @@ import OssManagerApi, {
import { dateFormat } from '@/utils/index' import { dateFormat } from '@/utils/index'
import { checkPermission } from '@/utils/permission' import { checkPermission } from '@/utils/permission'
import OssObjectProfile from './components/OssObjectProfile.vue' import OssObjectProfile from './components/OssObjectProfile.vue'
import OssObjectUploadDialog from './components/OssObjectUploadDialog.vue'
const kbUnit = 1 * 1024 const kbUnit = 1 * 1024
const mbUnit = kbUnit * 1024 const mbUnit = kbUnit * 1024
@ -180,7 +190,8 @@ const $contextmenu = Vue.prototype.$contextmenu
@Component({ @Component({
name: 'OssManagement', name: 'OssManagement',
components: { components: {
OssObjectProfile OssObjectProfile,
OssObjectUploadDialog
}, },
methods: { methods: {
checkPermission checkPermission
@ -226,6 +237,9 @@ export default class OssManagement extends Vue {
private objects = new Array<OssObject>() private objects = new Array<OssObject>()
private fileSystemRoot = new Array<string>() private fileSystemRoot = new Array<string>()
private showUploadOss = false
private uploadPath = ''
private getObjectRequest = new GetOssObjectRequest() private getObjectRequest = new GetOssObjectRequest()
private getBucketRequest = new GetOssContainerRequest() private getBucketRequest = new GetOssContainerRequest()
@ -330,6 +344,7 @@ export default class OssManagement extends Vue {
.deleteObject(this.bucket, oss.name, oss.path) .deleteObject(this.bucket, oss.name, oss.path)
.then(() => { .then(() => {
this.$notify.success(this.l('global.dataHasBeenDeleted', { name: oss.name })) this.$notify.success(this.l('global.dataHasBeenDeleted', { name: oss.name }))
this.handleClearObjects()
this.handleGetObjects() this.handleGetObjects()
}) })
} }
@ -343,11 +358,14 @@ export default class OssManagement extends Vue {
} }
private handleDownloadOssObject(oss: OssObject) { private handleDownloadOssObject(oss: OssObject) {
console.log(oss) if (!oss.isFolder) {
} const link = document.createElement('a')
link.style.display = 'none'
private handleFileSystemCommand(command: any) { link.href = OssManagerApi.generateOssUrl(this.bucket, oss.name, oss.path, '/api/')
console.log(command) link.setAttribute('download', oss.name)
document.body.appendChild(link)
link.click()
}
} }
private handleClearObjects() { private handleClearObjects() {
@ -364,11 +382,6 @@ export default class OssManagement extends Vue {
label: this.$t('fileSystem.addFolder'), label: this.$t('fileSystem.addFolder'),
disabled: !checkPermission(['AbpFileManagement.FileSystem.Create']), disabled: !checkPermission(['AbpFileManagement.FileSystem.Create']),
onClick: () => { onClick: () => {
let parent = ''
//
if (this.fileSystemRoot.length > 1) {
parent = this.fileSystemRoot.slice(1).join('')
}
this.$prompt(this.$t('global.pleaseInputBy', { key: this.$t('fileSystem.name') }).toString(), this.$prompt(this.$t('global.pleaseInputBy', { key: this.$t('fileSystem.name') }).toString(),
this.$t('fileSystem.addFolder').toString(), { this.$t('fileSystem.addFolder').toString(), {
showInput: true, showInput: true,
@ -380,7 +393,7 @@ export default class OssManagement extends Vue {
}).then((val: any) => { }).then((val: any) => {
const name = val.value + '/' const name = val.value + '/'
OssManagerApi OssManagerApi
.createFolder(this.bucket, name.replace('//', '/'), parent) .createFolder(this.bucket, name.replace('//', '/'), this.getCurrentPath())
.then(res => { .then(res => {
this.$message.success(this.$t('fileSystem.folderCreateSuccess', { name: res.name }).toString()) this.$message.success(this.$t('fileSystem.folderCreateSuccess', { name: res.name }).toString())
this.handleClearObjects() this.handleClearObjects()
@ -394,28 +407,25 @@ export default class OssManagement extends Vue {
label: this.$t('fileSystem.upload'), label: this.$t('fileSystem.upload'),
disabled: !checkPermission(['AbpFileManagement.FileSystem.FileManager.Create']), disabled: !checkPermission(['AbpFileManagement.FileSystem.FileManager.Create']),
onClick: () => { onClick: () => {
let path = '' this.uploadPath = this.getCurrentPath()
if (this.fileSystemRoot.length > 1) { this.showUploadOss = true
path = this.fileSystemRoot.slice(1).join('/')
}
}, },
divided: true divided: true
}, },
{
label: this.$t('fileSystem.bacthDownload'),
disabled: !checkPermission(['AbpFileManagement.FileSystem.FileManager.Download']),
onClick: () => {
const table = this.$refs.ossObjectTable as any
}
},
{ {
label: this.$t('fileSystem.bacthDelete'), label: this.$t('fileSystem.bacthDelete'),
disabled: true, // !checkPermission(['AbpFileManagement.FileSystem.FileManager.Delete']), disabled: !checkPermission(['AbpFileManagement.FileSystem.FileManager.Delete']),
onClick: () => { onClick: () => {
// //
// const table = this.$refs.ossObjectTable as any const table = this.$refs.ossObjectTable as any
// console.log(table)
// const selectFiles = table.selection.filter((x: any) => x.type === 1) OssManagerApi
.bulkDeleteObject(this.bucket, table.selection.map((x: any) => x.name), this.getCurrentPath())
.then(() => {
this.$message.success(this.l('successful'))
this.handleClearObjects()
this.handleGetObjects()
})
} }
} }
], ],
@ -427,6 +437,20 @@ export default class OssManagement extends Vue {
return false return false
} }
private onFileUploaded() {
this.$message.success(this.l('fileSystem.uploadSuccess'))
this.handleClearObjects()
this.handleGetObjects()
}
private getCurrentPath() {
let path = ''
if (this.fileSystemRoot.length > 1) {
path = this.fileSystemRoot.slice(1).join('')
}
return path
}
private l(name: string, values?: any[] | { [key: string]: any }) { private l(name: string, values?: any[] | { [key: string]: any }) {
return this.$t(name, values).toString() return this.$t(name, values).toString()
} }

Loading…
Cancel
Save