-
Notifications
You must be signed in to change notification settings - Fork 28
Expand file tree
/
Copy pathDropboxClientWrapper.cs
More file actions
154 lines (136 loc) · 4.95 KB
/
DropboxClientWrapper.cs
File metadata and controls
154 lines (136 loc) · 4.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Dropbox.Api;
using Dropbox.Api.Files;
namespace ManagedCode.Storage.Dropbox.Clients;
public class DropboxClientWrapper : IDropboxClientWrapper
{
private readonly DropboxClient _client;
public DropboxClientWrapper(DropboxClient client)
{
_client = client ?? throw new ArgumentNullException(nameof(client));
}
public async Task EnsureRootAsync(string rootPath, bool createIfNotExists, CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(rootPath))
{
return;
}
var normalized = Normalize(rootPath);
try
{
await _client.Files.GetMetadataAsync(normalized);
}
catch (ApiException<GetMetadataError> ex) when (ex.ErrorResponse.IsPath && ex.ErrorResponse.AsPath.Value.IsNotFound)
{
if (!createIfNotExists)
{
return;
}
await _client.Files.CreateFolderV2Async(normalized, autorename: false);
}
}
public async Task<DropboxItemMetadata> UploadAsync(string rootPath, string path, Stream content, string? contentType, CancellationToken cancellationToken)
{
var fullPath = Combine(rootPath, path);
var uploaded = await _client.Files.UploadAsync(fullPath, WriteMode.Overwrite.Instance, body: content);
var metadata = (await _client.Files.GetMetadataAsync(uploaded.PathLower)).AsFile;
return ToItem(metadata);
}
public async Task<Stream> DownloadAsync(string rootPath, string path, CancellationToken cancellationToken)
{
var fullPath = Combine(rootPath, path);
var response = await _client.Files.DownloadAsync(fullPath);
return await response.GetContentAsStreamAsync();
}
public async Task<bool> DeleteAsync(string rootPath, string path, CancellationToken cancellationToken)
{
var fullPath = Combine(rootPath, path);
await _client.Files.DeleteV2Async(fullPath);
return true;
}
public async Task<bool> ExistsAsync(string rootPath, string path, CancellationToken cancellationToken)
{
var fullPath = Combine(rootPath, path);
try
{
await _client.Files.GetMetadataAsync(fullPath);
return true;
}
catch (ApiException<GetMetadataError> ex) when (ex.ErrorResponse.IsPath && ex.ErrorResponse.AsPath.Value.IsNotFound)
{
return false;
}
}
public async Task<DropboxItemMetadata?> GetMetadataAsync(string rootPath, string path, CancellationToken cancellationToken)
{
var fullPath = Combine(rootPath, path);
try
{
var metadata = await _client.Files.GetMetadataAsync(fullPath);
return metadata.IsFile ? ToItem(metadata.AsFile) : null;
}
catch (ApiException<GetMetadataError> ex) when (ex.ErrorResponse.IsPath && ex.ErrorResponse.AsPath.Value.IsNotFound)
{
return null;
}
}
public async IAsyncEnumerable<DropboxItemMetadata> ListAsync(string rootPath, string? directory, [EnumeratorCancellation] CancellationToken cancellationToken)
{
var fullPath = Combine(rootPath, directory ?? string.Empty);
var list = await _client.Files.ListFolderAsync(fullPath);
foreach (var item in list.Entries)
{
if (item.IsFile)
{
yield return ToItem(item.AsFile);
}
}
while (list.HasMore)
{
list = await _client.Files.ListFolderContinueAsync(list.Cursor);
foreach (var item in list.Entries)
{
if (item.IsFile)
{
yield return ToItem(item.AsFile);
}
}
}
}
private static DropboxItemMetadata ToItem(FileMetadata file)
{
return new DropboxItemMetadata
{
Name = file.Name,
Path = file.PathLower ?? file.PathDisplay ?? string.Empty,
Size = file.Size,
ClientModified = file.ClientModified,
ServerModified = file.ServerModified
};
}
private static string Normalize(string path)
{
var normalized = path.Replace("\\", "/");
if (!normalized.StartsWith('/'))
{
normalized = "/" + normalized;
}
return normalized.TrimEnd('/') == string.Empty ? "/" : normalized.TrimEnd('/');
}
private static string Combine(string root, string path)
{
var normalizedRoot = Normalize(root);
var normalizedPath = path.Replace("\\", "/").Trim('/');
if (string.IsNullOrWhiteSpace(normalizedPath))
{
return normalizedRoot;
}
return normalizedRoot.EndsWith("/") ? normalizedRoot + normalizedPath : normalizedRoot + "/" + normalizedPath;
}
}