| | | 1 | | using Microsoft.Extensions.Options; |
| | | 2 | | using Services.FileStorageServices; |
| | | 3 | | |
| | | 4 | | namespace Services.LabelServices; |
| | | 5 | | |
| | | 6 | | public sealed class LabelFileStorage : ILabelFileStorage |
| | | 7 | | { |
| | | 8 | | private readonly IServerFileStorage _storage; |
| | | 9 | | private readonly string _folder; |
| | | 10 | | private readonly ILabelCatalogCache? _catalogCache; |
| | | 11 | | |
| | 6 | 12 | | public LabelFileStorage( |
| | 6 | 13 | | IServerFileStorage storage, |
| | 6 | 14 | | IOptions<LabelStorageOptions> options, |
| | 6 | 15 | | ILabelCatalogCache? catalogCache = null) |
| | | 16 | | { |
| | 6 | 17 | | _storage = storage; |
| | 6 | 18 | | _catalogCache = catalogCache; |
| | 6 | 19 | | _folder = string.IsNullOrWhiteSpace(options.Value.RelativeFolder) |
| | 6 | 20 | | ? "labels" |
| | 6 | 21 | | : options.Value.RelativeFolder.Trim('/'); |
| | 6 | 22 | | } |
| | | 23 | | |
| | 16 | 24 | | private string Path(string fileName) => $"{_folder}/{fileName}"; |
| | | 25 | | |
| | | 26 | | public Task<bool> ExistsAsync(string fileName, CancellationToken cancellationToken = default) => |
| | 4 | 27 | | _storage.ExistsAsync(Path(fileName), cancellationToken); |
| | | 28 | | |
| | | 29 | | public async Task<string?> FindExistingFileNameAsync( |
| | | 30 | | IEnumerable<string> candidateFileNames, CancellationToken cancellationToken = default) |
| | | 31 | | { |
| | 5 | 32 | | foreach (var fileName in candidateFileNames) |
| | | 33 | | { |
| | 2 | 34 | | if (await ExistsAsync(fileName, cancellationToken)) |
| | | 35 | | { |
| | 1 | 36 | | return fileName; |
| | | 37 | | } |
| | 1 | 38 | | } |
| | | 39 | | |
| | 0 | 40 | | return null; |
| | 1 | 41 | | } |
| | | 42 | | |
| | | 43 | | public async Task<byte[]?> TryDownloadAsync(string fileName, CancellationToken cancellationToken = default) |
| | | 44 | | { |
| | | 45 | | try |
| | | 46 | | { |
| | 3 | 47 | | var download = await _storage.OpenReadAsync(Path(fileName), cancellationToken); |
| | 2 | 48 | | await using var stream = download.Content; |
| | 2 | 49 | | using var memoryStream = new MemoryStream(); |
| | 2 | 50 | | await stream.CopyToAsync(memoryStream, cancellationToken); |
| | 2 | 51 | | return memoryStream.ToArray(); |
| | 0 | 52 | | } |
| | 1 | 53 | | catch (FileNotFoundException) |
| | | 54 | | { |
| | 1 | 55 | | return null; |
| | | 56 | | } |
| | 3 | 57 | | } |
| | | 58 | | |
| | | 59 | | public Task<ServerFileDownload> OpenReadAsync(string fileName, CancellationToken cancellationToken = default) => |
| | 0 | 60 | | _storage.OpenReadAsync(Path(fileName), cancellationToken); |
| | | 61 | | |
| | | 62 | | public async Task UploadAsync(byte[] content, string fileName, bool overwrite = true, CancellationToken cancellation |
| | | 63 | | { |
| | 7 | 64 | | using var stream = new MemoryStream(content); |
| | 7 | 65 | | await _storage.UploadAsync( |
| | 7 | 66 | | new ServerFileUpload(Path(fileName), stream, "application/pdf", overwrite), |
| | 7 | 67 | | cancellationToken); |
| | 7 | 68 | | _catalogCache?.Invalidate(); |
| | 7 | 69 | | } |
| | | 70 | | |
| | | 71 | | public Task<IReadOnlyList<ServerFileInfo>> ListAsync(CancellationToken cancellationToken = default) => |
| | 1 | 72 | | _storage.ListAsync(_folder, cancellationToken); |
| | | 73 | | |
| | | 74 | | public async Task DeleteAsync(string fileName, CancellationToken cancellationToken = default) |
| | | 75 | | { |
| | 2 | 76 | | await _storage.DeleteAsync(Path(fileName), cancellationToken); |
| | 2 | 77 | | _catalogCache?.Invalidate(); |
| | 2 | 78 | | } |
| | | 79 | | } |