Skip to content

Commit f17ebc8

Browse files
author
Meyn
committed
Implement InterceptCompletionAsync for GetRequest.
Fix SubsequentRequest functionality in LoadRequest. Resolve file information parsing issues in GetRequest partial downloads. Fix exception handling for Append mode in LoadRequest. Address chunk merging issues in LoadRequest. Update `Shard.Requests` to version 2.2.1. Update unit tests
1 parent f505fda commit f17ebc8

File tree

8 files changed

+222
-102
lines changed

8 files changed

+222
-102
lines changed

DownloadAssistant/Base/HttpGet.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using System;
2-
using System.Diagnostics;
1+
using System.Diagnostics;
32
using System.Net.Http.Headers;
43

54
namespace DownloadAssistant.Base

DownloadAssistant/DownloadAssistant.csproj

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<PackageProjectUrl></PackageProjectUrl>
1111
<PackageIcon>logo.png</PackageIcon>
1212
<PackageReadmeFile>README.md</PackageReadmeFile>
13-
<Version>1.0.5</Version>
13+
<Version>1.0.6</Version>
1414
<GenerateDocumentationFile>True</GenerateDocumentationFile>
1515
<Description>A free to use library as a download manager.
1616
Includes retry, priority, cancel, etc.. function.
@@ -26,7 +26,13 @@ Features:
2626
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
2727
<Company>Shard</Company>
2828
<Authors>Meyn</Authors>
29-
<PackageReleaseNotes>Update Shard.Requests to 2.2.0</PackageReleaseNotes>
29+
<PackageReleaseNotes>Implement InterceptCompletionAsync for GetRequest.
30+
Fix SubsequentRequest functionality in LoadRequest.
31+
Resolve file information parsing issues in GetRequest partial downloads.
32+
Fix exception handling for Append mode in LoadRequest.
33+
Address chunk merging issues in LoadRequest.
34+
Update `Shard.Requests` to version 2.2.1.
35+
Update unit tests</PackageReleaseNotes>
3036
<RepositoryUrl>https://github.com/TypNull/DownloadAssistant</RepositoryUrl>
3137
</PropertyGroup>
3238

@@ -46,7 +52,7 @@ Features:
4652
</ItemGroup>
4753

4854
<ItemGroup>
49-
<PackageReference Include="Shard.Requests" Version="2.2.0" />
55+
<PackageReference Include="Shard.Requests" Version="2.2.1" />
5056
</ItemGroup>
5157

5258
<ItemGroup>

DownloadAssistant/Options/GetRequestOptions.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ public long? MaxByte
126126
/// </value>
127127
public Notify<GetRequest>? InfosFetched { get; init; }
128128

129+
/// <summary>
130+
/// Gets or sets a function that intercepts the completion of the request, allowing for custom asynchronous logic to modify or prevent the completion.
131+
/// </summary>
132+
public Func<GetRequest, Task>? InterceptCompletionAsync { get; set; }
133+
129134
/// <summary>
130135
/// Initializes a new instance of the <see cref="GetRequestOptions"/> class.
131136
/// </summary>
@@ -146,6 +151,7 @@ protected GetRequestOptions(GetRequestOptions options) : base(options)
146151
MinByte = options.MinByte;
147152
MaxByte = options.MaxByte;
148153
SupportsHeadRequest = options.SupportsHeadRequest;
154+
InterceptCompletionAsync = options.InterceptCompletionAsync;
149155
Progress = options.Progress;
150156
Range = options.Range;
151157
InfosFetched = options.InfosFetched;

DownloadAssistant/Requests/GetRequest.cs

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -141,19 +141,14 @@ public async Task RunToCompleatedAsync()
141141
{
142142
await Task;
143143
_progress.Report(1f);
144-
SynchronizationContext.Post(delegate (object? o)
145-
{
146-
Options.RequestCompleated?.Invoke((GetRequest)o!, FilePath);
147-
}, this);
148-
144+
SynchronizationContext.Post((o) => Options.RequestCompleated?.Invoke((GetRequest)o!, FilePath), this);
149145
}
150146
}
151147

152148
/// <summary>
153149
/// Initializes a new instance of the <see cref="HttpGet"/> class that holds the HTTP information.
154150
/// </summary>
155-
private void SetHttpGet()
156-
=> _httpGet = new(GetPresetRequestMessage(new(HttpMethod.Get, Url)), Options.SupportsHeadRequest)
151+
private void SetHttpGet() => _httpGet = new(GetPresetRequestMessage(new(HttpMethod.Get, Url)), Options.SupportsHeadRequest)
157152
{
158153
Token = Token,
159154
Range = Range,
@@ -173,12 +168,15 @@ protected override async Task<RequestReturn> RunRequestAsync()
173168
result = await LoadAsync();
174169
result.FailedReturn?.Dispose();
175170
if (State == RequestState.Running && result.Successful)
171+
{
176172
_progress.Report(1f);
173+
await (Options.InterceptCompletionAsync?.Invoke(this) ?? Task.CompletedTask);
174+
}
177175
}
178176
catch (Exception ex)
179177
{
180178
AddException(ex);
181-
Debug.Assert(true, ex.Message);
179+
Debug.Assert(false, ex.Message);
182180
}
183181

184182
return result;
@@ -198,7 +196,7 @@ private async Task<RequestReturn> LoadAsync()
198196
return new(false, FilePath, res);
199197
bool noBytesWritten = BytesWritten <= 0;
200198

201-
if (noBytesWritten)
199+
if (string.IsNullOrEmpty(ContentName))
202200
SetFileInfo(res);
203201

204202
if (IsFinished())
@@ -247,7 +245,6 @@ private async Task<HttpResponseMessage> ReloadActions(HttpResponseMessage res, b
247245
PartialContentLength = null;
248246
}
249247

250-
251248
return res;
252249
}
253250

@@ -283,11 +280,10 @@ private void SetFileInfo(HttpResponseMessage res)
283280
break;
284281
case WriteMode.AppendOrTruncate:
285282
LoadWrittenBytes();
286-
if (BytesWritten > ContentLength)
287-
{
288-
IOManager.Create(FilePath);
289-
BytesWritten = 0;
290-
}
283+
if (BytesWritten <= ContentLength)
284+
break;
285+
IOManager.Create(FilePath);
286+
BytesWritten = 0;
291287
break;
292288
case WriteMode.Append:
293289
LoadWrittenBytes();
@@ -299,7 +295,6 @@ private void SetFileInfo(HttpResponseMessage res)
299295
}
300296
break;
301297
}
302-
303298
Options.InfosFetched?.Invoke(this);
304299
}
305300

DownloadAssistant/Requests/LoadRequest.cs

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -180,11 +180,11 @@ private void CreateRequest()
180180
_chunkHandler.Add(CreateChunk(0, options));
181181

182182
Task.Run(() =>
183-
{
184-
for (int i = 1; i < Options.Chunks; i++)
185-
_chunkHandler.Add(CreateChunk(i, options));
186-
AutoStart();
187-
});
183+
{
184+
for (int i = 1; i < Options.Chunks; i++)
185+
_chunkHandler.Add(CreateChunk(i, options));
186+
AutoStart();
187+
});
188188
return;
189189
}
190190

@@ -194,7 +194,8 @@ private void CreateRequest()
194194
RequestFailed = OnFailure,
195195
SpeedReporter = Options.CreateSpeedReporter ? new() { Timeout = Options.SpeedReporterTimeout } : null,
196196
RequestStarted = Options.RequestStarted,
197-
RequestCompleated = OnCompletion,
197+
SubsequentRequest = Options.SubsequentRequest,
198+
InterceptCompletionAsync = OnCompletionAsync
198199
};
199200

200201
InnerRequest = new GetRequest(Url, options);
@@ -215,8 +216,8 @@ private GetRequest CreateChunk(int index, GetRequestOptions options)
215216
Range = new LoadRange(new Index(index), Options.Chunks),
216217
SpeedReporter = Options.CreateSpeedReporter ? new() { Timeout = Options.SpeedReporterTimeout } : null,
217218
Filename = $"{(string.IsNullOrWhiteSpace(Options.Filename) ? "*.*" : Options.Filename)}.{1 + index}_chunk",
218-
RequestCompleated = OnCompletion,
219219
RequestFailed = OnFailure,
220+
InterceptCompletionAsync = OnCompletionAsync
220221
};
221222
if (index == 0)
222223
options.RequestStarted += Options.RequestStarted;
@@ -263,7 +264,6 @@ private void OnInfosFetched(GetRequest? request)
263264
Filename = request.ContentName;
264265
try
265266
{
266-
267267
if (IsChunked)
268268
{
269269
_chunkHandler.SetInfos(request);
@@ -276,7 +276,6 @@ private void OnInfosFetched(GetRequest? request)
276276
return;
277277
}
278278

279-
280279
SynchronizationContext.Post((o) => Options.InfosFetched?.Invoke((LoadRequest)o!), this);
281280
ExcludedExtensions(request.ContentExtension);
282281
}
@@ -315,7 +314,6 @@ private void CreatePlaceholderFile(GetRequest request)
315314
break;
316315
case WriteMode.Overwrite:
317316
IOManager.Create(Destination);
318-
319317
_writeMode = WriteMode.AppendOrTruncate;
320318
break;
321319
case WriteMode.AppendOrTruncate:
@@ -365,17 +363,20 @@ private async void CreatePlaceholderFiles(GetRequest request)
365363
case WriteMode.Append:
366364
if (File.Exists(Destination) && new FileInfo(Destination).Length > 0)
367365
{
368-
AddException(new FileLoadException($"The file {Filename} at {Destination} already exists. Please change the WriteMode or delete the file."));
366+
AddException(new FileLoadException($"The file '{Filename}' already exists at '{Destination}'. Resolve by changing WriteMode, deleting the file, or avoiding chunked requests."));
369367
OnFailure(this, null);
370368
break;
371369
}
372370
if (!File.Exists(TempDestination))
373371
break;
374-
if (new FileInfo(TempDestination).Length < (request.FullContentLength ?? (request.PartialContentLength * Options.Chunks)))
372+
long appendByteLength = new FileInfo(TempDestination).Length;
373+
if (appendByteLength > (request.FullContentLength ?? (request.PartialContentLength * Options.Chunks)))
375374
{
376375
AddException(new FileLoadException($"The file specified in {TempDestination} has exceeded the expected filesize of the actual downloaded file. Please adjust the WriteMode."));
377376
OnFailure(this, null);
377+
break;
378378
}
379+
await _chunkHandler.TrySetBytesAsync(appendByteLength);
379380
break;
380381
case WriteMode.AppendOrTruncate:
381382
IOManager.Create(Destination);
@@ -411,25 +412,29 @@ private void ExcludedExtensions(string contentExtension)
411412
/// Handles the completion of the request.
412413
/// </summary>
413414
/// <param name="request">The <see cref="IRequest"/> instance that has completed.</param>
414-
/// <param name="_">This parameter is not used.</param>
415415
/// <remarks>
416416
/// This method handles the completion of the request. If the request is chunked, it starts merging the chunks. If the request is not chunked, it moves the temporary file to the destination.
417417
/// </remarks>
418-
private async void OnCompletion(IRequest? request, string? _)
418+
private async Task OnCompletionAsync(IRequest? request)
419419
{
420420
if (request == null)
421421
return;
422422
bool canMove = false;
423423
if (IsChunked)
424424
{
425-
if (Options.MergeWhileProgress || _chunkHandler.Requests.All(request => request.State == RequestState.Compleated))
425+
_chunkHandler.MarkChunkAsCompleted((GetRequest)request);
426+
if (Options.MergeWhileProgress || _chunkHandler.AllCompleted)
426427
canMove = await _chunkHandler.StartMergeTo(TempDestination);
427428
}
428429
else
429430
canMove = true;
430431

431432
if (canMove)
433+
{
434+
if (Options.SubsequentRequest != null)
435+
((GetRequest)request).TrySetSubsequentRequest(Options.SubsequentRequest);
432436
TempToDestination();
437+
}
433438
}
434439

435440
/// <summary>
@@ -522,12 +527,11 @@ public override void Cancel()
522527
/// <summary>
523528
/// Releases all resources used by the <see cref="LoadRequest"/>.
524529
/// </summary>
525-
#pragma warning disable CA1816
526530
public override void Dispose()
527-
#pragma warning restore CA1816
528531
{
529532
InnerRequest.Dispose();
530533
base.Dispose();
534+
GC.SuppressFinalize(this);
531535
}
532536
}
533537
}

0 commit comments

Comments
 (0)