How to: Manage binary files with the Dapr Binary Store .NET SDK
Use the Dapr.BinaryStore package to store and retrieve files using a Dapr binary store component. The client streams file content in chunks, so you can work with large files without loading the entire file into memory. In this guide, you will:
- Register and configure
DaprBinaryStoreClient - Upload and download files using streams
- Choose between streaming and in-memory operations
- Bind a typed client to a store with the source generator
Prerequisites
- Dapr CLI
- An initialized Dapr environment
- .NET 8, .NET 9, .NET 10, or .NET 11
- Dapr runtime 1.19 or later
- The Dapr.BinaryStore NuGet package
- A binary store component configured in Dapr
.NET framework support
Be advised that .NET 8 and .NET 9 reach end of support in November 2026. Support for both will be dropped in Dapr v1.20; only .NET 10 and .NET 11 will be supported through the end of 2027.Install the package in your project:
dotnet add package Dapr.BinaryStore
Configure an in-memory binary store
For local development, create a components directory in your application directory and save the following component as components\filestore.yaml:
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: filestore
spec:
type: binarystore.in-memory
version: v1
metadata:
- name: maxSize
value: "4Mi"
- name: maxTotalSize
value: "512Mi"
This component stores files in the Dapr sidecar’s memory without requiring an external storage service. It allows files up to 4 MiB and a combined total of 512 MiB. Data is lost when the sidecar stops and is not shared across sidecars, so use it for local development and testing rather than durable storage.
The component’s metadata.name, filestore, is the store name supplied to the client methods or the [BinaryStore] attribute in the examples below.
Register the client
Register the client in dependency injection. By default, it reads the Dapr endpoint and API token from the environment or IConfiguration.
using Dapr.BinaryStore.Extensions;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDaprBinaryStoreClient();
var app = builder.Build();
Start the application from its project directory with its Dapr sidecar, loading the in-memory component from components:
dapr run --app-id binary-store-example --resources-path .\components -- dotnet run
If you need to override the endpoint, configure the client builder:
builder.Services.AddDaprBinaryStoreClient((sp, clientBuilder) =>
{
clientBuilder.UseGrpcEndpoint("http://localhost:50001");
});
Upload and download a file
Resolve the registered client and pass the binary store component name, a file name, and a stream. The example uses the filestore component configured above. Place a report.pdf file no larger than 4 MiB in your application’s working directory before running the example. Add the following code after var app = builder.Build(); in Program.cs, with the using directives at the top of the file.
using Dapr.BinaryStore;
using Microsoft.Extensions.DependencyInjection;
var client = app.Services.GetRequiredService<DaprBinaryStoreClient>();
const string storeName = "filestore";
const string fileName = "uploads/report.pdf";
await using (var source = File.OpenRead("report.pdf"))
{
await client.SetBinaryFileAsync(storeName, fileName, source);
}
await using (var destination = File.Create("downloaded-report.pdf"))
{
await client.GetBinaryFileAsync(storeName, fileName, destination);
}
The example uploads report.pdf to the in-memory store as uploads/report.pdf and downloads it to downloaded-report.pdf. Run the remaining examples against the same sidecar to use the uploaded file before deleting it.
The Stream overload of SetBinaryFileAsync reads the input stream from its current position and sends it to the runtime in chunks. The default upload chunk size is 32 KiB; pass chunkSize to choose another positive size. Set overwrite: true to replace an existing file. By default, an upload fails if the file already exists.
File names can include nested paths such as uploads/report.pdf. Avoid a leading or trailing slash, empty path segments, . or .. segments, and the characters \, *, ?, [, ], and #; the Dapr runtime rejects these names.
Work with in-memory content
For content that already fits in memory, pass ReadOnlyMemory<byte> to upload or use GetBinaryFileBytesAsync to retrieve the complete file:
byte[] content = [0x01, 0x02, 0x03];
await client.SetBinaryFileAsync(storeName, "data.bin", content);
byte[] downloaded = await client.GetBinaryFileBytesAsync(storeName, "data.bin");
GetBinaryFileBytesAsync buffers the whole file in memory. Prefer GetBinaryFileAsync or GetBinaryFileChunksAsync for large files:
await using var chunkDestination = File.Create("downloaded-report-from-chunks.pdf");
await foreach (var chunk in client.GetBinaryFileChunksAsync(storeName, fileName))
{
await chunkDestination.WriteAsync(chunk);
}
Delete a file
await client.DeleteBinaryFileAsync(storeName, fileName);
Use a store-bound typed client
The package includes a source generator for a typed client that is bound to one component. Define a partial interface that extends IDaprBinaryStoreClient and use [BinaryStore] to specify the component name:
using Dapr.BinaryStore;
[BinaryStore("filestore")]
public partial interface IFileStore : IDaprBinaryStoreClient
{
}
Register the generated client after registering DaprBinaryStoreClient:
builder.Services
.AddDaprBinaryStoreClient()
.WithFileStore();
The generated WithFileStore method registers an implementation of IFileStore. Inject that interface where it is needed; its methods are the same as IDaprBinaryStoreClient but do not take a store name:
public sealed class ReportService(IFileStore fileStore)
{
public Task SaveAsync(string name, Stream content, CancellationToken cancellationToken) =>
fileStore.SetBinaryFileAsync(name, content, cancellationToken: cancellationToken);
}