with one click
shiny-http-transfers
// Guide for generating code that uses Shiny.NET HTTP Transfers for background uploads and downloads on iOS/Android, Windows, Linux, macOS, and Blazor WASM (Service Worker Background Sync)
// Guide for generating code that uses Shiny.NET HTTP Transfers for background uploads and downloads on iOS/Android, Windows, Linux, macOS, and Blazor WASM (Service Worker Background Sync)
Generate code using Shiny.BluetoothLE.Hosting, a BLE peripheral hosting library for .NET with GATT server, advertising, and managed characteristic patterns
Shiny BluetoothLE client/central operations for scanning, connecting, and communicating with BLE peripherals
Background job scheduling and execution for .NET MAUI (iOS/Android native OS schedulers) and in-process jobs for plain .NET, Linux, macOS, and Blazor WASM using Shiny.Jobs
GPS tracking, geofence monitoring, and motion activity recognition for .NET MAUI, iOS, and Android using Shiny.Locations
Core infrastructure, hosting, DI, key-value stores, lifecycle hooks, and platform abstractions for Shiny on .NET MAUI, iOS, and Android
Guide for implementing push notifications in .NET MAUI apps using Shiny.Push (native FCM/APNs) and Shiny.Push.AzureNotificationHubs
| name | shiny-http-transfers |
| description | Guide for generating code that uses Shiny.NET HTTP Transfers for background uploads and downloads on iOS/Android, Windows, Linux, macOS, and Blazor WASM (Service Worker Background Sync) |
| auto_invoke | true |
| triggers | ["http transfer","background upload","background download","file upload","file download","transfer manager","HttpTransferManager","IHttpTransferManager","IHttpTransferDelegate","HttpTransferRequest","HttpTransferMonitor","Shiny.Net.Http","azure blob upload","aws s3 upload","s3 upload","AwsS3UploadRequest","multipart upload","download file","upload file","transfer progress"] |
Background HTTP upload and download management. On iOS, backed by native NSURLSession background sessions. On Android, Windows, Linux, macOS, and base .NET, backed by an in-process managed loop using HttpClient + IConnectivity that wakes on connectivity changes and supports resumable downloads via HTTP Range requests (uploads always restart); on Android this loop runs inside a foreground service. On Blazor WASM, backed by the Service Worker Background Sync API (IndexedDB queue drained by the SW via fetch() while the tab is closed).
Use this skill when the user needs to:
| Item | Value |
|---|---|
| NuGet | Shiny.Net.Http, Shiny.Net.Http.Blazor |
| Namespace | Shiny.Net.Http |
| Platforms | iOS (native NSURLSession); Android, Windows, Linux, macOS, .NET base (managed HttpClient loop); Blazor WASM (Service Worker) |
| DI Setup | services.AddHttpTransfers<TDelegate>() (iOS/Android/Windows), services.AddHttpClientTransfers<TDelegate>() (Linux/macOS/plain .NET), or services.AddBlazorHttpTransfers<TDelegate>() (Blazor) |
The registration extension methods live in the Shiny namespace and are available on IServiceCollection.
In your MauiProgram.cs:
using Shiny;
builder.Services.AddHttpTransfers<MyHttpTransferDelegate>();
Create a class that implements IHttpTransferDelegate (or inherits from the abstract HttpTransferDelegate base class for built-in retry logic):
using Shiny.Net.Http;
public class MyHttpTransferDelegate : HttpTransferDelegate
{
public MyHttpTransferDelegate(
ILogger<MyHttpTransferDelegate> logger,
IHttpTransferManager manager
) : base(logger, manager, maxErrorRetries: 3) { }
public override Task OnCompleted(HttpTransferRequest request)
{
// Handle successful transfer completion
return Task.CompletedTask;
}
// Optional: override for 401 handling
protected override Task<HttpTransferRequest?> OnAuthorizationFailed(
HttpTransferRequest request, int retries)
{
// Return a new request with refreshed auth headers, or null to cancel
return Task.FromResult<HttpTransferRequest?>(null);
}
}
On Android, the delegate must also implement IAndroidForegroundServiceDelegate:
#if ANDROID
public partial class MyHttpTransferDelegate : IAndroidForegroundServiceDelegate
{
public void Configure(AndroidX.Core.App.NotificationCompat.Builder builder)
{
builder
.SetContentTitle("File Transfer")
.SetContentText("Transferring files in the background");
}
}
#endif
On non-platform .NET hosts (Linux, macOS server, console apps, etc.) call AddHttpClientTransfers<TDelegate>() instead of AddHttpTransfers<TDelegate>(). It registers HttpClientHttpTransferManager backed by an HttpClient loop driven by IConnectivity that wakes immediately on connectivity changes. Downloads resume after network interruption via HTTP Range requests (Range: bytes=N-, FileMode.Append when the server responds with 206 Partial Content); uploads always restart from scratch.
You must register an IConnectivity implementation yourself (e.g. AddConnectivity() from Shiny.Core.Linux or Shiny.Core.Blazor). A default JSON filesystem repository is registered automatically and persists transfer state to {LocalApplicationData}/Shiny across process restarts.
Cancelled downloads clean up any partial file on disk so a subsequent re-queue starts fresh.
Shiny.Net.Http.Blazor)using Shiny;
builder.Services.AddBlazorHttpTransfers<MyDelegate>(opts =>
{
opts.ServiceWorkerPath = "./_content/Shiny.Net.Http.Blazor/http-transfer-sw.js";
});
The Blazor package uses the Service Worker Background Sync API. Queued transfers are written to IndexedDB; the Service Worker's sync event handler drains the queue via fetch() and stores download bodies as Blobs back into IndexedDB. When the tab reopens, the C# HttpTransferManager reconciles results from IndexedDB and fires the IHttpTransferDelegate callbacks.
Ship the bundled SW file or import its handlers from your own service worker:
// my-sw.js
importScripts('./_content/Shiny.Net.Http.Blazor/http-transfer-sw.js');
Blazor limitations (v1):
Blob; partial-body appending is not supported.Blobs. Fine for small/medium files; very large uploads should wait for a future OPFS streaming path.(manager as Shiny.Net.Http.Blazor.HttpTransferManager).GetDownloadBytes(identifier) which reads the blob back out of IndexedDB as a byte[].Do not confuse with Shiny.Jobs on Blazor — Jobs only run while the tab is open because the WASM runtime cannot execute inside a Service Worker. HTTP transfers are the one exception because fetch() is pure JS that the SW can run on its own.
When generating code that uses Shiny HTTP Transfers, follow these conventions:
IHttpTransferManager via dependency injection; never instantiate directly.HttpTransferRequest requires 4 positional parameters: Identifier, Uri, TransferType, LocalFilePath:
var request = new HttpTransferRequest(
"my-download",
"https://example.com/file.zip",
TransferType.Download,
Path.Combine(FileSystem.AppDataDirectory, "file.zip")
);
await transferManager.Queue(request);
Identifier for each HttpTransferRequest so individual transfers can be tracked and cancelled.LocalFilePath points to an existing file before queuing.UseMeteredConnection = false to restrict large transfers to Wi-Fi only.TransferType: UploadMultipart for form-based uploads, UploadRaw for streaming the file body directly, Download for downloads.WhenUpdateReceived() for a global stream of all transfer updates.WatchTransfer(identifier) extension method to observe a single transfer that completes or errors.WatchCount() to reactively display the number of active transfers.HttpTransferMonitor -- call Start() to begin monitoring and bind to the Transfers collection of HttpTransferObject items. These implement INotifyPropertyChanged.TransferHttpContent.FromJson(obj) to attach a JSON body to an upload.TransferHttpContent.FromFormData(...) to attach form-encoded data.AzureBlobStorageUploadRequest for Azure Blob Storage uploads -- call .WithBlobContainer(tenant, container) or .WithCustomUri(uri), configure auth via .WithSasToken() or .WithSharedKeyAuthorization(), then call .Build() to get an HttpTransferRequest.AwsS3UploadRequest for AWS S3 uploads -- call .WithBucket(bucket, region), configure auth via .WithPresignedUrl() or .WithCredentials(accessKeyId, secretAccessKey), optionally set .WithObjectKey(), .WithContentType(), .WithStorageClass(), then call .Build() to get an HttpTransferRequest. Uses AWS Signature V4 signing with UNSIGNED-PAYLOAD -- no AWS SDK required.AppleHttpTransferRequest (inherits HttpTransferRequest) when Apple-specific options are needed (e.g., AllowsConstrainedNetworkAccess, AllowsCellularAccess, AssumesHttp3Capable).HttpClient extension methods Upload(...) and Download(...) which return IObservable<TransferProgress> with real-time progress.INativeConfigurator implementation to customize NSUrlSessionConfiguration and NSMutableUrlRequest objects before they are sent.HttpTransferDelegate provides built-in retry and 401-handling logic. Only implement IHttpTransferDelegate directly if you need full control.request.AssertValid() to check the request is well-formed before calling Queue().HttpTransferMonitor to UI, pass a scheduler (e.g., RxApp.MainThreadScheduler or SynchronizationContext.Current) to Start().HttpTransferMonitor implements IDisposable. Dispose it when the page or view model is torn down.UseMeteredConnection = false for large files so the system waits for an unmetered (Wi-Fi) connection.