< Summary - Kestrun — Combined Coverage

Information
Class: Kestrun.Client.KrHttpDownloads
Assembly: Kestrun
File(s): /home/runner/work/Kestrun/Kestrun/src/CSharp/Kestrun/Client/KrHttpDownloads.cs
Tag: Kestrun/Kestrun@9d3a582b2d63930269564a7591aa77ef297cadeb
Line coverage
0%
Covered lines: 0
Uncovered lines: 28
Coverable lines: 28
Total lines: 66
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 18
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
DownloadToFileAsync()0%342180%

File(s)

/home/runner/work/Kestrun/Kestrun/src/CSharp/Kestrun/Client/KrHttpDownloads.cs

#LineLine coverage
 1// src/CSharp/Kestrun.Net/KrHttp.Downloads.cs
 2using System.Net.Http.Headers;
 3
 4namespace Kestrun.Client;
 5
 6/// <summary>
 7/// Helper methods for common HTTP download scenarios.
 8/// </summary>
 9public static class KrHttpDownloads
 10{
 11    /// <summary>
 12    /// Streams an HTTP response body to a file, supporting very large payloads and optional resume.
 13    /// Returns the final file length in bytes.
 14    /// </summary>
 15    public static async Task<long> DownloadToFileAsync(
 16        HttpClient client,
 17        HttpRequestMessage request,
 18        string filePath,
 19        bool resume = false,
 20        int bufferBytes = 1 << 20, // 1 MiB
 21        CancellationToken cancellationToken = default)
 22    {
 023        ArgumentNullException.ThrowIfNull(client);
 024        ArgumentNullException.ThrowIfNull(request);
 025        if (string.IsNullOrWhiteSpace(filePath))
 26        {
 027            throw new ArgumentNullException(nameof(filePath));
 28        }
 29
 030        if (bufferBytes < 81920)
 31        {
 032            bufferBytes = 81920;
 33        }
 34
 035        var mode = FileMode.Create;
 036        if (resume && File.Exists(filePath))
 37        {
 38            // Resume support: if file exists, set Range header and append to file.
 039            var existing = new FileInfo(filePath).Length;
 040            if (existing > 0)
 41            {
 042                request.Headers.Range = new RangeHeaderValue(existing, null);
 043                mode = FileMode.Append;
 44            }
 45        }
 46
 047        using var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken
 048                                        .ConfigureAwait(false);
 049        _ = response.EnsureSuccessStatusCode();
 50
 051        await using var source = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
 052        _ = Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(filePath))!);
 053        await using var target = new FileStream(
 054            filePath,
 055            mode,
 056            FileAccess.Write,
 057            FileShare.None,
 058            bufferBytes,
 059            FileOptions.Asynchronous | FileOptions.SequentialScan);
 60
 061        await source.CopyToAsync(target, bufferBytes, cancellationToken).ConfigureAwait(false);
 62
 063        await target.FlushAsync(cancellationToken).ConfigureAwait(false);
 064        return new FileInfo(filePath).Length;
 065    }
 66}

Methods/Properties

DownloadToFileAsync()