Title image of Upload to Cloudflare R2 in C#

Upload to Cloudflare R2 in C#

29 July 2023

·
Cloudflare
C#

R2 is Cloudflare’s object storage solution equivalent to AWS’s S3 or Azure’s Blob Storage. It’s becoming popular because of its global distribution and zero egress charges. This post covers how to upload files to the service in C#. Cloudflare doesn’t provide any direct C# SDK for using R2, but don’t worry there is still an SDK we can use 😉

AWS S3 Compatibility

Cloudflare is very blunt with its marketing for R2. It’s obvious that R2 is positioned as a direct competitor to AWS’s S3. The main selling point of R2 is the zero egress charges for accessing the data which is something that has always annoyed S3 users. Cloudflare has pushed this point so far that they have set up a bandwidth alliance with other cloud providers. The alliance describes itself as a “group of forward-thinking cloud and networking companies that are committed to discounting or waiving data transfer (also known as bandwidth) fees”. The alliance does not include AWS.

All this positioning against S3 has led Cloudflare to do something interesting: R2 has been built with a S3-compatible API. This means R2’s API has the same schema and layout as S3. They’ve done this to make it easy for clients to migrate from S3 to R2. Because it’s the same API clients don’t have to change their code.

All this preamble is to explain that even though Cloudflare doesn’t provide a C# SDK we can actually use the AWS S3 SDK with R2!

Uploading with the S3 SDK

Setting up Cloudflare

We need four pieces of information from Cloudflare to make this work: Bucket Name, AccountId, Access Key and Access Secret.

We specify the bucket name when we create the bucket:

Getting the bucket name from Cloudflare

Get your account id from the R2 overview page:

Getting the account id from the cloudflare r2 overview page

Get your access key and secret by creating an R2 API token:

Creating a R2 API token to get the access key and secret

Using the S3 SDK

To install the SDK add the AWSSDK.S3 Nuget package to the project. Do this via visual studio tooling or by running the following command:

dotnet add package AWSSDK.S3

There are two important settings to configure when using the SDK.

1) Set the service URL of the S3 client to point at Cloudflare:

var s3Client = new AmazonS3Client(
    accessKey,
    accessSecret,
    new AmazonS3Config
    {
        ServiceURL = $"https://{accountId}.r2.cloudflarestorage.com"
    });

2) Disable payload signing on the request because it is different between Cloudflare and AWS:

var request = new PutObjectRequest
{
    BucketName = "thisisabucketname",
    Key = imageName,
    InputStream = image,
    ContentType = type,
    DisablePayloadSigning = true
};

Complete code

public class CloudflareClient : ICloudflareClient
{
    private readonly string accountId;
    private readonly string accessKey;
    private readonly string accessSecret;

    public CloudflareClient(string accountId, string accessKey, string accessSecret)
    {
        this.accountId = accountId;
        this.accessKey = accessKey;
        this.accessSecret = accessSecret;
    }

    public async Task UploadImage(Stream image, string imageName, string type)
    {
        var s3Client = new AmazonS3Client(
            accessKey,
            accessSecret,
            new AmazonS3Config
            {
                ServiceURL = $"https://{accountId}.r2.cloudflarestorage.com"
            });

        var request = new PutObjectRequest
        {
            BucketName = "thisisabucketname",
            Key = imageName,
            InputStream = image,
            ContentType = type,
            DisablePayloadSigning = true
        };

        var response = await s3Client.PutObjectAsync(request);

        if(response.HttpStatusCode != System.Net.HttpStatusCode.OK && response.HttpStatusCode != System.Net.HttpStatusCode.Accepted)
        {
            throw new Exception("Upload to Cloudflare R2 failed");
        }
    }
}

So yeah that’s how we can upload files to Cloudflare R2 via the AWS S3 SDK 🙂