Ebee.Cloudflare.R2 3.0.0

Prefix Reserved
dotnet add package Ebee.Cloudflare.R2 --version 3.0.0
                    
NuGet\Install-Package Ebee.Cloudflare.R2 -Version 3.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Ebee.Cloudflare.R2" Version="3.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Ebee.Cloudflare.R2" Version="3.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Ebee.Cloudflare.R2" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Ebee.Cloudflare.R2 --version 3.0.0
                    
#r "nuget: Ebee.Cloudflare.R2, 3.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Ebee.Cloudflare.R2@3.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Ebee.Cloudflare.R2&version=3.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Ebee.Cloudflare.R2&version=3.0.0
                    
Install as a Cake Tool

Ebee.Cloudflare.R2

A comprehensive .NET client library for Cloudflare R2 storage, providing a simple and intuitive API for managing buckets, objects, signed URLs, and multipart uploads.

NuGet Version NuGet Downloads License

Features

  • Bucket Management: Create, list, and delete R2 buckets
  • Object Operations: Upload, download, copy, delete, and list objects
  • Streaming Downloads: Stream large objects without buffering them in memory
  • Metadata Support: Full support for custom metadata and headers
  • Signed URLs: Generate pre-signed URLs for secure access
  • Multipart Uploads: Handle large file uploads efficiently
  • Encryption: Support for server-side encryption (SSE-S3, SSE-C)
  • Async/Await: Full asynchronous support with cooperative cancellation
  • Strongly Typed: Immutable, strongly-typed request/response models
  • Error Handling: Detailed exception handling with R2-specific errors
  • Dependency Injection: Built-in DI container support

Installation

dotnet add package Ebee.Cloudflare.R2

Quick Start

1. Configure Services

using Ebee.Cloudflare.R2;

services.AddR2Client(options =>
{
    options.AccountId = "your-account-id";
    options.AccessKeyId = "your-access-key-id";
    options.SecretAccessKey = "your-secret-access-key";
});

⚠️ Never hard-code credentials in source. The literals above are for illustration only. See Configuration & Secrets for the recommended, config-driven setup.

2. Use the Client

using Ebee.Cloudflare.R2;
using Ebee.Cloudflare.R2.Objects.Models;

public class FileService
{
    private readonly IR2Client _r2Client;

    public FileService(IR2Client r2Client)
    {
        _r2Client = r2Client;
    }

    public async Task<string?> UploadFileAsync(string bucketName, string key, Stream content)
    {
        var request = new R2PutObjectRequest
        {
            BucketName = bucketName,
            Key = key,
            ContentStream = content,          // the caller owns and disposes this stream
            ContentType = "application/octet-stream"
        };

        var response = await _r2Client.PutObjectAsync(request);
        return response.ETag;
    }
}

Documentation

For detailed documentation and usage examples, please refer to the following topics:

API Overview

IR2Client exposes operations two ways — pick whichever reads better in your code:

// 1. Flattened convenience methods directly on IR2Client:
await r2Client.PutObjectAsync(request);
await r2Client.GetObjectAsync(request);
await r2Client.GetObjectStreamAsync(request);   // streaming download
r2Client.GenerateGetSignedUrl(request);

// 2. Grouped sub-clients, if you prefer to inject a narrower surface:
IBucketsClient Buckets;                 // Bucket operations
IObjectsClient Objects;                 // Object operations
ISignedUrlsClient SignedUrls;           // Pre-signed URLs
IMultipartUploadsClient MultipartUploads; // Large file uploads

Both surfaces call the same underlying implementations. You can also inject any of the grouped interfaces (IObjectsClient, etc.) directly instead of IR2Client.

Configuration & Secrets

Credentials are sensitive — keep them out of source control. The recommended approach is to bind configuration from a secure source using the IConfiguration overload:

// Reads the "R2" section by default (override with a second argument).
services.AddR2Client(builder.Configuration);
services.AddR2Client(builder.Configuration, sectionName: "CloudflareR2");

Expected configuration shape (e.g. appsettings.json, user-secrets, or Key Vault):

{
  "R2": {
    "AccountId": "your-account-id",
    "AccessKeyId": "your-access-key-id",
    "SecretAccessKey": "your-secret-access-key"
  }
}
  • Local development: use user secrets (dotnet user-secrets set "R2:SecretAccessKey" "...").
  • Production: use a secret store such as Azure Key Vault / AWS Secrets Manager, or environment variables mapped through configuration (the .NET environment-variable provider binds R2__AccountId, R2__AccessKeyId, R2__SecretAccessKey using the __ separator).

Configuration is validated at registration time: if AccountId, AccessKeyId, or SecretAccessKey is missing, AddR2Client throws an InvalidOperationException immediately rather than failing later on the first request.

Additional options

Option Default Description
EndpointUrl https://{AccountId}.r2.cloudflarestorage.com Override the R2 endpoint.
DisablePayloadSigning true Required for streaming uploads to R2.
DisableChecksumValidation true Disables the SDK's default upload checksum. See the security note below.

🔒 Upload integrity note. For Cloudflare R2 compatibility this client, by default, disables AWS request payload signing and the SDK's default checksum validation on PutObject/UploadPart. This means uploads are not protected by an end-to-end SDK checksum. If your R2 setup supports it, you can opt back into checksum validation by setting options.DisableChecksumValidation = false. You can always supply your own ContentMD5 on multipart parts for integrity.

Dependency Injection & Thread Safety

  • AddR2Client registers the underlying IAmazonS3 client as a singleton and the R2 clients (IR2Client and the grouped interfaces) as scoped.
  • The clients are stateless wrappers over the thread-safe IAmazonS3, so they are safe to use concurrently. Resolve IR2Client from DI rather than constructing it manually.

Streaming Downloads & Disposal

GetObjectAsync buffers the whole object in memory (convenient for small payloads). For large objects, use GetObjectStreamAsync, which hands you the live network stream and never buffers the full payload:

using Ebee.Cloudflare.R2.Objects.Models;

var request = new R2GetObjectRequest { BucketName = "my-bucket", Key = "large-file.zip" };
await using var response = await r2Client.GetObjectStreamAsync(request);
await response.ContentStream.CopyToAsync(destinationStream);
  • R2GetObjectStreamResponse and R2GetObjectResponse are IDisposable — dispose them (using/await using) to release the underlying stream and HTTP connection.
  • Request objects do not own streams you assign to ContentStream; you are responsible for disposing any stream you supply.

Error Handling

All operations may throw R2Exception with detailed error information. Cancellation is cooperative — a cancelled CancellationToken surfaces as OperationCanceledException, not R2Exception:

try
{
    var response = await _r2Client.GetObjectAsync(request, cancellationToken);
}
catch (OperationCanceledException)
{
    // the operation was cancelled
}
catch (R2Exception ex)
{
    Console.WriteLine($"R2 operation failed: {ex.Message}");

    // Check inner exception for AWS S3 specific details
    if (ex.InnerException is AmazonS3Exception s3Ex)
    {
        Console.WriteLine($"S3 Error Code: {s3Ex.ErrorCode}");
    }
}

Getting R2 Credentials

  1. Log in to your Cloudflare Dashboard
  2. Navigate to R2 Object Storage
  3. Go to Manage R2 API tokens
  4. Create a new API token with appropriate permissions
  5. Note your Account ID from the R2 dashboard

Examples Repository

Check out the samples/ directory for complete working examples:

Requirements

  • .NET 6.0, .NET 8.0, .NET 9.0, or .NET 10.0
  • Valid Cloudflare R2 credentials

Contributing

We welcome contributions! Please see our Contributing Guidelines for details.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support


Happy coding with Cloudflare R2!

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
3.0.0 134 7/15/2026
2.0.0 169 2/8/2026
1.1.2 137 1/13/2026
1.1.1 238 10/20/2025
1.1.0 224 10/19/2025
1.0.1 164 10/4/2025
1.0.0 159 10/4/2025

v3.0.0: Added streaming downloads (GetObjectStreamAsync); configurable upload integrity (payload signing / checksum validation); startup options validation; cancellation now propagates as OperationCanceledException. Breaking: response models are now init-only immutable, request models use the 'required' keyword, and content-carrying request types no longer implement IDisposable (callers own their streams). See CHANGELOG.md.