Skip to content

Commit 24b49dd

Browse files
committed
feat: implement cancelation token on some of upload method
1 parent 6e84b32 commit 24b49dd

File tree

4 files changed

+52
-22
lines changed

4 files changed

+52
-22
lines changed

Storage/Extensions/HttpClientProgress.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,19 +90,19 @@ internal static class HttpClientProgress
9090
}
9191
}
9292

93-
public static Task<HttpResponseMessage> UploadFileAsync(this HttpClient client, Uri uri, string filePath, Dictionary<string, string>? headers = null, Progress<float>? progress = null)
93+
public static Task<HttpResponseMessage> UploadFileAsync(this HttpClient client, Uri uri, string filePath, Dictionary<string, string>? headers = null, Progress<float>? progress = null, CancellationToken cancellationToken = default)
9494
{
9595
var fileStream = new FileStream(filePath, mode: FileMode.Open, FileAccess.Read);
96-
return UploadAsync(client, uri, fileStream, headers, progress);
96+
return UploadAsync(client, uri, fileStream, headers, progress, cancellationToken);
9797
}
9898

99-
public static Task<HttpResponseMessage> UploadBytesAsync(this HttpClient client, Uri uri, byte[] data, Dictionary<string, string>? headers = null, Progress<float>? progress = null)
99+
public static Task<HttpResponseMessage> UploadBytesAsync(this HttpClient client, Uri uri, byte[] data, Dictionary<string, string>? headers = null, Progress<float>? progress = null, CancellationToken cancellationToken = default)
100100
{
101101
var stream = new MemoryStream(data);
102-
return UploadAsync(client, uri, stream, headers, progress);
102+
return UploadAsync(client, uri, stream, headers, progress, cancellationToken);
103103
}
104104

105-
public static async Task<HttpResponseMessage> UploadAsync(this HttpClient client, Uri uri, Stream stream, Dictionary<string, string>? headers = null, Progress<float>? progress = null)
105+
public static async Task<HttpResponseMessage> UploadAsync(this HttpClient client, Uri uri, Stream stream, Dictionary<string, string>? headers = null, Progress<float>? progress = null, CancellationToken cancellationToken = default)
106106
{
107107
var content = new ProgressableStreamContent(stream, 4096, progress);
108108

@@ -119,7 +119,7 @@ public static async Task<HttpResponseMessage> UploadAsync(this HttpClient client
119119
}
120120
}
121121

122-
var response = await client.PostAsync(uri, content);
122+
var response = await client.PostAsync(uri, content, cancellationToken);
123123

124124
if (!response.IsSuccessStatusCode)
125125
{

Storage/Interfaces/IStorageFileApi.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Threading;
34
using System.Threading.Tasks;
45

56
namespace Supabase.Storage.Interfaces
@@ -23,10 +24,10 @@ public interface IStorageFileApi<TFileObject>
2324
Task<bool> Copy(string fromPath, string toPath, DestinationOptions? options = null);
2425
Task<TFileObject?> Remove(string path);
2526
Task<List<TFileObject>?> Remove(List<string> paths);
26-
Task<string> Update(byte[] data, string supabasePath, FileOptions? options = null, EventHandler<float>? onProgress = null);
27-
Task<string> Update(string localFilePath, string supabasePath, FileOptions? options = null, EventHandler<float>? onProgress = null);
28-
Task<string> Upload(byte[] data, string supabasePath, FileOptions? options = null, EventHandler<float>? onProgress = null, bool inferContentType = true);
29-
Task<string> Upload(string localFilePath, string supabasePath, FileOptions? options = null, EventHandler<float>? onProgress = null, bool inferContentType = true);
27+
Task<string> Update(byte[] data, string supabasePath, FileOptions? options = null, EventHandler<float>? onProgress = null, CancellationToken cancellationToken = default);
28+
Task<string> Update(string localFilePath, string supabasePath, FileOptions? options = null, EventHandler<float>? onProgress = null, CancellationToken cancellationToken = default);
29+
Task<string> Upload(byte[] data, string supabasePath, FileOptions? options = null, EventHandler<float>? onProgress = null, bool inferContentType = true, CancellationToken cancellationToken = default);
30+
Task<string> Upload(string localFilePath, string supabasePath, FileOptions? options = null, EventHandler<float>? onProgress = null, bool inferContentType = true, CancellationToken cancellationToken = default);
3031
Task<string> UploadToSignedUrl(byte[] data, UploadSignedUrl url, FileOptions? options = null, EventHandler<float>? onProgress = null, bool inferContentType = true);
3132
Task<string> UploadToSignedUrl(string localFilePath, UploadSignedUrl url, FileOptions? options = null, EventHandler<float>? onProgress = null, bool inferContentType = true);
3233
Task<UploadSignedUrl> CreateUploadSignedUrl(string supabasePath);

Storage/StorageFileApi.cs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.IO;
55
using System.Linq;
66
using System.Net.Http;
7+
using System.Threading;
78
using System.Threading.Tasks;
89
using System.Web;
910
using Newtonsoft.Json;
@@ -172,14 +173,14 @@ await Helpers.MakeRequest<List<FileObject>>(HttpMethod.Post, $"{Url}/object/list
172173
/// <param name="inferContentType"></param>
173174
/// <returns></returns>
174175
public async Task<string> Upload(string localFilePath, string supabasePath, FileOptions? options = null,
175-
EventHandler<float>? onProgress = null, bool inferContentType = true)
176+
EventHandler<float>? onProgress = null, bool inferContentType = true, CancellationToken cancellationToken = default)
176177
{
177178
options ??= new FileOptions();
178179

179180
if (inferContentType)
180181
options.ContentType = MimeMapping.MimeUtility.GetMimeMapping(localFilePath);
181182

182-
var result = await UploadOrUpdate(localFilePath, supabasePath, options, onProgress);
183+
var result = await UploadOrUpdate(localFilePath, supabasePath, options, onProgress, cancellationToken);
183184
return result;
184185
}
185186

@@ -193,14 +194,14 @@ public async Task<string> Upload(string localFilePath, string supabasePath, File
193194
/// <param name="inferContentType"></param>
194195
/// <returns></returns>
195196
public async Task<string> Upload(byte[] data, string supabasePath, FileOptions? options = null,
196-
EventHandler<float>? onProgress = null, bool inferContentType = true)
197+
EventHandler<float>? onProgress = null, bool inferContentType = true, CancellationToken cancellationToken = default)
197198
{
198199
options ??= new FileOptions();
199200

200201
if (inferContentType)
201202
options.ContentType = MimeMapping.MimeUtility.GetMimeMapping(supabasePath);
202203

203-
var result = await UploadOrUpdate(data, supabasePath, options, onProgress);
204+
var result = await UploadOrUpdate(data, supabasePath, options, onProgress, cancellationToken);
204205
return result;
205206
}
206207

@@ -288,10 +289,10 @@ public async Task<string> UploadToSignedUrl(byte[] data, UploadSignedUrl signedU
288289
/// <param name="onProgress"></param>
289290
/// <returns></returns>
290291
public Task<string> Update(string localFilePath, string supabasePath, FileOptions? options = null,
291-
EventHandler<float>? onProgress = null)
292+
EventHandler<float>? onProgress = null, CancellationToken cancellationToken = default)
292293
{
293294
options ??= new FileOptions();
294-
return UploadOrUpdate(localFilePath, supabasePath, options, onProgress);
295+
return UploadOrUpdate(localFilePath, supabasePath, options, onProgress, cancellationToken);
295296
}
296297

297298
/// <summary>
@@ -303,10 +304,10 @@ public Task<string> Update(string localFilePath, string supabasePath, FileOption
303304
/// <param name="onProgress"></param>
304305
/// <returns></returns>
305306
public Task<string> Update(byte[] data, string supabasePath, FileOptions? options = null,
306-
EventHandler<float>? onProgress = null)
307+
EventHandler<float>? onProgress = null, CancellationToken cancellationToken = default)
307308
{
308309
options ??= new FileOptions();
309-
return UploadOrUpdate(data, supabasePath, options, onProgress);
310+
return UploadOrUpdate(data, supabasePath, options, onProgress, cancellationToken);
310311
}
311312

312313
/// <summary>
@@ -480,7 +481,7 @@ public async Task<UploadSignedUrl> CreateUploadSignedUrl(string supabasePath)
480481
}
481482

482483
private async Task<string> UploadOrUpdate(string localPath, string supabasePath, FileOptions options,
483-
EventHandler<float>? onProgress = null)
484+
EventHandler<float>? onProgress = null, CancellationToken cancellationToken = default)
484485
{
485486
Uri uri = new Uri($"{Url}/object/{GetFinalPath(supabasePath)}");
486487

@@ -506,7 +507,7 @@ private async Task<string> UploadOrUpdate(string localPath, string supabasePath,
506507
if (onProgress != null)
507508
progress.ProgressChanged += onProgress;
508509

509-
await Helpers.HttpUploadClient!.UploadFileAsync(uri, localPath, headers, progress);
510+
await Helpers.HttpUploadClient!.UploadFileAsync(uri, localPath, headers, progress, cancellationToken);
510511

511512
return GetFinalPath(supabasePath);
512513
}
@@ -520,7 +521,7 @@ private static string ParseMetadata(Dictionary<string, string> metadata)
520521
}
521522

522523
private async Task<string> UploadOrUpdate(byte[] data, string supabasePath, FileOptions options,
523-
EventHandler<float>? onProgress = null)
524+
EventHandler<float>? onProgress = null, CancellationToken cancellationToken = default)
524525
{
525526
Uri uri = new Uri($"{Url}/object/{GetFinalPath(supabasePath)}");
526527

@@ -546,7 +547,7 @@ private async Task<string> UploadOrUpdate(byte[] data, string supabasePath, File
546547
if (onProgress != null)
547548
progress.ProgressChanged += onProgress;
548549

549-
await Helpers.HttpUploadClient!.UploadBytesAsync(uri, data, headers, progress);
550+
await Helpers.HttpUploadClient!.UploadBytesAsync(uri, data, headers, progress, cancellationToken);
550551

551552
return GetFinalPath(supabasePath);
552553
}

StorageTests/StorageFileTests.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.IO;
44
using System.Linq;
55
using System.Reflection;
6+
using System.Threading;
67
using System.Threading.Tasks;
78
using Microsoft.VisualStudio.TestTools.UnitTesting;
89
using Supabase.Storage;
@@ -142,6 +143,33 @@ public async Task UploadArbitraryByteArray()
142143

143144
await _bucket.Remove(new List<string> { name });
144145
}
146+
147+
[TestMethod("File: Cancel Upload Arbitrary Byte Array")]
148+
public async Task UploadArbitraryByteArrayCanceled()
149+
{
150+
var tsc = new TaskCompletionSource<bool>();
151+
using var ctk = new CancellationTokenSource(TimeSpan.FromMilliseconds(1));
152+
153+
var data = new byte[20 * 1024 * 1024];
154+
var rng = new Random();
155+
rng.NextBytes(data);
156+
var name = $"{Guid.NewGuid()}.bin";
157+
158+
var action = async () =>
159+
{
160+
await _bucket.Upload(data, name, null, (_, _) => tsc.TrySetResult(true), true, ctk.Token);
161+
};
162+
163+
await Assert.ThrowsExceptionAsync<TaskCanceledException>(action);
164+
165+
var list = await _bucket.List();
166+
Assert.IsNotNull(list);
167+
168+
var existing = list.Find(item => item.Name == name);
169+
Assert.IsNull(existing);
170+
171+
await _bucket.Remove([name]);
172+
}
145173

146174
[TestMethod("File: Download")]
147175
public async Task DownloadFile()

0 commit comments

Comments
 (0)