Skip to content
Introducing AI Conversations: Natural Language Interaction for Your Apps! Learn More

HTTP Transfers

GitHubGitHub stars for shinyorg/shiny
DownloadsNuGet downloads for Shiny.Net.Http
BlazorNuGet downloads for Shiny.Net.Http.Blazor
Operating Systems
Android
iOS
Windows
macOS
Linux
Web

Shiny HTTP Transfers enables background uploads and downloads that continue even when your app is suspended. On iOS/Android, transfers are managed by the OS and will resume after app restarts. On Windows, Linux, macOS, and plain .NET hosts a managed HttpClient loop drives transfers and supports resumable downloads via HTTP Range requests. On Blazor WebAssembly, transfers are queued to IndexedDB and drained by a Service Worker via the Background Sync API.

  • Background uploads and downloads
  • Multipart and raw upload support
  • Progress tracking with speed and ETA
  • Automatic resume after app restart
  • Resumable downloads on plain .NET (Linux/macOS/Windows) via HTTP Range requests
  • Metered/unmetered network control
  • Managed transfer list for UI binding
  • Cross-platform: iOS, Android, Windows, Linux, macOS, Blazor WebAssembly
PlatformPackageBacking
iOSShiny.Net.HttpNSURLSession background session
AndroidShiny.Net.HttpForeground service + WorkManager
WindowsShiny.Net.HttpManaged HttpClient loop
Linux / macOS / Plain .NETShiny.Net.HttpManaged HttpClient + IConnectivity loop; resumable downloads via HTTP Range
Blazor WebAssemblyShiny.Net.Http.BlazorService Worker Background Sync + IndexedDB; downloads not resumable
Shiny.Net.HttpNuGet package Shiny.Net.Http
Shiny.Hosting.MauiNuGet package Shiny.Hosting.Maui

Implement IHttpTransferDelegate to handle transfer completion and errors in the background.

public partial class MyTransferDelegate : IHttpTransferDelegate
{
readonly ILogger<MyTransferDelegate> logger;
public MyTransferDelegate(ILogger<MyTransferDelegate> logger)
{
this.logger = logger;
}
public Task OnCompleted(HttpTransferRequest request)
{
this.logger.LogInformation("Transfer completed: {Id}", request.Identifier);
return Task.CompletedTask;
}
public Task OnError(HttpTransferRequest request, int statusCode, Exception ex)
{
this.logger.LogError(ex, "Transfer failed: {Id}, Status: {Status}", request.Identifier, statusCode);
return Task.CompletedTask;
}
}

On Android, background transfers run as a foreground service. Customize the notification:

#if ANDROID
public partial class MyTransferDelegate : IAndroidForegroundServiceDelegate
{
public void Configure(AndroidX.Core.App.NotificationCompat.Builder builder)
{
builder
.SetContentTitle("My App")
.SetContentText("Transferring files...")
.SetSmallIcon(Resource.Mipmap.appicon);
}
}
#endif
// iOS / Android / Windows / Linux / macOS / plain .NET
services.AddHttpTransfers<MyTransferDelegate>();
// Blazor WebAssembly
services.AddBlazorHttpTransfers<MyTransferDelegate>(opts =>
{
// Optional — defaults to the bundled Shiny service worker
opts.ServiceWorkerPath = "./_content/Shiny.Net.Http.Blazor/http-transfer-sw.js";
});

On Blazor, ship the bundled SW at the configured path, or import its handlers from your own service worker:

my-sw.js
importScripts('./_content/Shiny.Net.Http.Blazor/http-transfer-sw.js');
claude plugin marketplace add shinyorg/skills
claude plugin install shiny-client@shiny
copilot plugin marketplace add https://github.com/shinyorg/skills
copilot plugin install shiny-client@shiny
View shiny-client Plugin