Image providers answer one question: where does the source image come from? Every incoming request is offered to the registered providers in order, and the first provider whose Match function returns true owns the request.
That means provider order matters. If two providers can both match the same path, put the more specific one first or narrow its Match predicate so the wrong provider does not claim the request.
PhysicalFileSystemProvider is the default source provider registered by AddImageSharp().
- It resolves images from the web root by default.
PhysicalFileSystemProviderOptions.ProviderRootPathcan benull, absolute, or relative to the application content root.PhysicalFileSystemProviderOptions.ProcessingBehaviorstill defaults toProcessingBehavior.CommandOnly, but the default middleware callback injectsautoorient=truewhen the request does not already containautoorient, so local image requests are usually processed anyway.
using SixLabors.ImageSharp.Web;
using SixLabors.ImageSharp.Web.Providers;
builder.Services.AddImageSharp()
.Configure<PhysicalFileSystemProviderOptions>(options =>
{
options.ProviderRootPath = "assets";
options.ProcessingBehavior = ProcessingBehavior.CommandOnly;
});If you want a provider fixed to IWebHostEnvironment.WebRootFileProvider with no extra options, WebRootImageProvider is also available.
If you want truly command-only processing for local files, changing ProcessingBehavior is no longer sufficient on its own. You must also replace or suppress the default OnParseCommandsAsync behavior that inserts autoorient=true.
ImageSharp.Web stops at the first provider whose Match function returns true. It does not continue searching if that provider later decides the request is invalid, so keep these rules in mind:
- Register more specific providers before more general ones.
- Keep
Matchpredicates mutually exclusive whenever possible. - Use
InsertProvider(...)when provider precedence matters more than registration order.
Cloud providers in particular usually want a path prefix such as a container or bucket name so they can distinguish their requests cheaply.
Install the Azure provider package:
dotnet add package SixLabors.ImageSharp.Web.Providers.AzureThen configure one or more containers:
using SixLabors.ImageSharp.Web;
using SixLabors.ImageSharp.Web.Azure.Providers;
builder.Services.AddImageSharp()
.ClearProviders()
.Configure<AzureBlobStorageImageProviderOptions>(options =>
{
options.BlobContainers.Add(new AzureBlobContainerClientOptions
{
ConnectionString = builder.Configuration["Azure:ConnectionString"]!,
ContainerName = "public-images"
});
})
.AddProvider<AzureBlobStorageImageProvider>();Requests are matched by container name at the start of the path:
/public-images/avatars/jane.png?width=200
AzureBlobStorageImageProvider uses ProcessingBehavior.All, so it can serve both processed and commandless requests.
Install the AWS provider package:
dotnet add package SixLabors.ImageSharp.Web.Providers.AWSThen configure one or more buckets:
using SixLabors.ImageSharp.Web;
using SixLabors.ImageSharp.Web.AWS.Providers;
builder.Services.AddImageSharp()
.ClearProviders()
.Configure<AWSS3StorageImageProviderOptions>(options =>
{
options.S3Buckets.Add(new AWSS3BucketClientOptions
{
BucketName = "public-images",
Region = "us-east-1",
AccessKey = builder.Configuration["AWS:AccessKey"],
AccessSecret = builder.Configuration["AWS:SecretKey"]
});
})
.AddProvider<AWSS3StorageImageProvider>();Requests are matched by bucket name at the start of the path:
/public-images/avatars/jane.png?width=200
If your public URL shape does not naturally include the bucket name, use URL rewriting before ImageSharp.Web or implement a custom provider.
Implement IImageProvider when you need a new source backend. Your provider is responsible for three things:
- deciding whether it owns the request via
Match; - deciding whether the request is valid via
IsValidRequest(...); - returning an
IImageResolverthat can open the source stream and report source metadata.
If your source already fits an IFileProvider-style model, FileProviderImageProvider is the easiest base class to start from.
- Put providers in the order you want requests to be matched.
- Keep original source storage separate from processed cache storage.
- Return accurate source metadata so stale cache detection works.
- Implement a custom provider only when existing filesystem, Azure, or S3 providers do not match the source model.