Direct-to-S3 / Azure tus 1.0 resume IndexedDB Golden Retriever 30 locales Webcam & screen capture

Custom Storage Provider

Implement a custom storage provider to save files to any destination: cloud storage, databases, or networked file systems.

What you should see: files stored through a provider you supply rather than the built-in filesystem one. The client side is unchanged — only the server's destination differs. Accepts up to 100 MB.
Drag & drop files here, or paste from clipboard
<core-upload asp-upload-url="/api/upload/upload"
 asp-multiple="true"
 asp-progress="true"
 asp-auto-upload="true"
 asp-max-size="100MB">
</core-upload>

<!-- Server-side: implement IStorageProvider -->
public class MyCloudStorageProvider : IStorageProvider
{
 public async Task<string> SaveAsync(
 Stream stream, string fileName, string contentType)
 {
 // Upload to your cloud storage
 var blobClient = _container
 .GetBlobClient(fileName);
 await blobClient.UploadAsync(stream);
 return blobClient.Uri.ToString();
 }

 public async Task DeleteAsync(string fileId)
 {
 var blobClient = _container
 .GetBlobClient(fileId);
 await blobClient.DeleteIfExistsAsync();
 }

 public async Task<Stream> GetAsync(string fileId)
 {
 var blobClient = _container
 .GetBlobClient(fileId);
 return await blobClient.OpenReadAsync();
 }
}

// In Program.cs
builder.Services.AddCoreUpload(options =>
{
 options.UseStorageProvider<MyCloudStorageProvider>();
});

Storage is an interface, not a setting

IUploaderProvider decides where bytes end up. Implement SaveAsync, AppendAsync, GetInfoAsync, OpenReadAsync, DeleteAsync and PersistAsync, register it in DI, and uploads land wherever you decide — object storage, a database, a network share. FileSystemProvider is the one that ships.

AppendAsync is the method that makes chunking work

Chunked uploads arrive as a sequence, so the provider must append rather than overwrite. A provider that treats every chunk as a fresh SaveAsync ends up with only the last one — which looks like a truncated file rather than an obvious error, and is the classic mistake when writing one of these.

FindByHashAsync is optional and has a default implementation returning null. Implement it only if you want server-side deduplication; skipping it costs nothing.