Crate cf_r2_sdk

Source
Expand description

§Unofficial Cloudflare R2 SDK

This is the “Unofficial Cloudflare R2 SDK”.

It can upload, download, and delete binary data or files to Cloudflare R2.

This crate is based on cloudflare-r2-rs (License: Apache-2.0, Owner: milen-denev) and r2sync (License: MIT, Owner: Songmu).

date: 2025-01-18

This crate is solved this problem by adding the following S3Client config.

requestChecksumCalculation: “WHEN_REQUIRED”, responseChecksumValidation: “WHEN_REQUIRED”,

Reference: https://developers.cloudflare.com/r2/examples/aws/aws-sdk-js-v3/

§Struct

builder::Builder

operator::Operator

§How to use

§1. Create a aws_sdk_s3::Client object

Set the “bucket name”, “access key id”, “secret access key”, “endpoint url”, and “region”.

Default value of region is “auto” (region is option field).

use cf_r2_sdk::builder::Builder;
use cf_r2_sdk::error::Error;
use dotenvy::dotenv;
use std::env;

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Error> {
    // load .env file
    dotenv().expect(".env file not found.");
    // insert a environment variable
    let bucket_name = env::var("BUCKET_NAME").expect("BUCKET_NAME not found in .env file.");
    let endpoint_url: String =
        env::var("ENDPOINT_URL").expect("ENDPOINT_URL not found in .env file.");
    let access_key_id: String =
        env::var("ACCESS_KEY_ID").expect("ACCESS_KEY_ID not found in .env file.");
    let secret_access_key: String =
        env::var("SECRET_ACCESS_KEY").expect("SECRET_ACCESS_KEY not found in .env file.");
    let region: String = env::var("REGION").expect("REGION not found in .env file.");

    let object: cf_r2_sdk::operator::Operator = Builder::new()
        .set_bucket_name(bucket_name)
        .set_access_key_id(access_key_id)
        .set_secret_access_key(secret_access_key)
        .set_endpoint(endpoint_url)
        .set_region(region)
        .create_client_result()?;
    Ok(())
}

§2. Operate R2 object strage

§Upload binary data
use cf_r2_sdk::builder::Builder;
use cf_r2_sdk::error::Error;
use dotenvy::dotenv;
use std::env;

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Error> {
   // load .env file
   dotenv().expect(".env file not found.");
   // insert a environment variable
   let bucket_name = env::var("BUCKET_NAME").expect("BUCKET_NAME not found in .env file.");
   let endpoint_url: String =
       env::var("ENDPOINT_URL").expect("ENDPOINT_URL not found in .env file.");
   let access_key_id: String =
       env::var("ACCESS_KEY_ID").expect("ACCESS_KEY_ID not found in .env file.");
   let secret_access_key: String =
      env::var("SECRET_ACCESS_KEY").expect("SECRET_ACCESS_KEY not found in .env file.");
   let region: String = env::var("REGION").expect("REGION not found in .env file.");

   let object: cf_r2_sdk::operator::Operator = Builder::new()
       .set_bucket_name(bucket_name)
       .set_access_key_id(access_key_id)
       .set_secret_access_key(secret_access_key)
       .set_endpoint(endpoint_url)
       .set_region(region)
       .create_client_result()?;

   // upload binary data
   object
       .upload_binary("sample.txt", "test/plain", b"Hello, World!", None)
       .await?;
   Ok(())
}
§upload file
use cf_r2_sdk::builder::Builder;
use cf_r2_sdk::error::Error;
use dotenvy::dotenv;
use std::env;

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Error> {
   // load .env file
   dotenv().expect(".env file not found.");
   // insert a environment variable
   let bucket_name = env::var("BUCKET_NAME").expect("BUCKET_NAME not found in .env file.");
   let endpoint_url: String =
       env::var("ENDPOINT_URL").expect("ENDPOINT_URL not found in .env file.");
   let access_key_id: String =
       env::var("ACCESS_KEY_ID").expect("ACCESS_KEY_ID not found in .env file.");
   let secret_access_key: String =
      env::var("SECRET_ACCESS_KEY").expect("SECRET_ACCESS_KEY not found in .env file.");
   let region: String = env::var("REGION").expect("REGION not found in .env file.");

   let object: cf_r2_sdk::operator::Operator = Builder::new()
       .set_bucket_name(bucket_name)
       .set_access_key_id(access_key_id)
       .set_secret_access_key(secret_access_key)
       .set_endpoint(endpoint_url)
       .set_region(region)
       .create_client_result()?;

   // upload file
   object
       .upload_file("sample.jpg", "image/jpeg", "data/sample.jpg", None)
       .await?;
   Ok(())
}
§download binary data
use cf_r2_sdk::builder::Builder;
use cf_r2_sdk::error::Error;
use dotenvy::dotenv;
use std::env;

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Error> {
   // load .env file
   dotenv().expect(".env file not found.");
   // insert a environment variable
   let bucket_name = env::var("BUCKET_NAME").expect("BUCKET_NAME not found in .env file.");
   let endpoint_url: String =
       env::var("ENDPOINT_URL").expect("ENDPOINT_URL not found in .env file.");
   let access_key_id: String =
       env::var("ACCESS_KEY_ID").expect("ACCESS_KEY_ID not found in .env file.");
   let secret_access_key: String =
      env::var("SECRET_ACCESS_KEY").expect("SECRET_ACCESS_KEY not found in .env file.");
   let region: String = env::var("REGION").expect("REGION not found in .env file.");

   let object: cf_r2_sdk::operator::Operator = Builder::new()
       .set_bucket_name(bucket_name)
       .set_access_key_id(access_key_id)
       .set_secret_access_key(secret_access_key)
       .set_endpoint(endpoint_url)
       .set_region(region)
       .create_client_result()?;

    object
       .upload_binary("sample.txt", "test/plain", b"Hello, World!", None)
       .await?;

   // download binary data
   let bin: Vec<u8> = object.download("sample.txt").await?;

   println!("{:?}", bin);
   Ok(())
}
§delete file
use cf_r2_sdk::builder::Builder;
use cf_r2_sdk::error::Error;
use dotenvy::dotenv;
use std::env;

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Error> {
   // load .env file
   dotenv().expect(".env file not found.");
   // insert a environment variable
   let bucket_name = env::var("BUCKET_NAME").expect("BUCKET_NAME not found in .env file.");
   let endpoint_url: String =
       env::var("ENDPOINT_URL").expect("ENDPOINT_URL not found in .env file.");
   let access_key_id: String =
       env::var("ACCESS_KEY_ID").expect("ACCESS_KEY_ID not found in .env file.");
   let secret_access_key: String =
      env::var("SECRET_ACCESS_KEY").expect("SECRET_ACCESS_KEY not found in .env file.");
   let region: String = env::var("REGION").expect("REGION not found in .env file.");

   let object: cf_r2_sdk::operator::Operator = Builder::new()
       .set_bucket_name(bucket_name)
       .set_access_key_id(access_key_id)
       .set_secret_access_key(secret_access_key)
       .set_endpoint(endpoint_url)
       .set_region(region)
       .create_client_result()?;

   object
       .upload_binary("sample.txt", "test/plain", b"Hello, World!", None)
       .await?;

   // delete file
   object
       .delete("sample.txt")
       .await?;

   Ok(())
}
§get file names vector
use cf_r2_sdk::builder::Builder;
use cf_r2_sdk::error::Error;
use dotenvy::dotenv;
use std::env;

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Error> {
   // load .env file
   dotenv().expect(".env file not found.");
   // insert a environment variable
   let bucket_name = env::var("BUCKET_NAME").expect("BUCKET_NAME not found in .env file.");
   let endpoint_url: String =
       env::var("ENDPOINT_URL").expect("ENDPOINT_URL not found in .env file.");
   let access_key_id: String =
       env::var("ACCESS_KEY_ID").expect("ACCESS_KEY_ID not found in .env file.");
   let secret_access_key: String =
      env::var("SECRET_ACCESS_KEY").expect("SECRET_ACCESS_KEY not found in .env file.");
   let region: String = env::var("REGION").expect("REGION not found in .env file.");

   let object: cf_r2_sdk::operator::Operator = Builder::new()
       .set_bucket_name(bucket_name)
       .set_access_key_id(access_key_id)
       .set_secret_access_key(secret_access_key)
       .set_endpoint(endpoint_url)
       .set_region(region)
       .create_client_result()?;

   object
       .upload_binary("sample.txt", "test/plain", b"Hello, World!", None)
       .await?;

   // get file names vector
   let file_names: Vec<String> = object.list_objects().await?;

   for file_name in file_names {
      println!("{}", file_name);
   }

   Ok(())
}

Modules§

builder
error
operator