Skip to content

yavuzakyazici/cloudflare_boto3_example

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 

Repository files navigation

Here is an example CloudFlare R2, S3 compatible storage bucket working with FastAPI. I had trouble finding a good example so here it is. I hope this helps someone..

from fastapi import FastAPI, UploadFile
import os
from dotenv import load_dotenv
import boto3
from botocore.exceptions import ClientError

"""
All of these params below should be in a .env file loaded with load_dotenv()

load_dotenv()

R2_BUCKET_NAME = os.getenv("R2_BUCKET_NAME")
ACCESS_KEY_ID = os.getenv("ACCESS_KEY_ID")
SECRET_ACCESS_KEY_ID = os.getenv("SECRET_ACCESS_KEY_ID")
ENDPOINT_URL_DEFAULT = os.getenv("ENDPOINT_URL_DEFAULT")
REGION_NAME = os.getenv("REGION_NAME")
"""

"""
These are dummy place holder params
You should get real params from CloudFlare R2 after creating your bucket
and your API Key at CloudFlare Dashboard
This example obivously will NOT work before creating your bucket and getting API key
"""
R2_BUCKET_NAME = "My_Bucket_Name"
ACCESS_KEY_ID = "My_Access_Key_Id"
SECRET_ACCESS_KEY_ID = "My_Secret_Access_Key_Id"
ENDPOINT_URL_DEFAULT = "My_Endpoint_Url_Default"
REGION_NAME = "auto"


app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Welcome to CloudFlare R2 Boto3 example"}


"""
create your boto3 client
"""
s3 = boto3.client(
    service_name ="s3",
    endpoint_url = ENDPOINT_URL_DEFAULT,
    aws_access_key_id = ACCESS_KEY_ID,
    aws_secret_access_key = SECRET_ACCESS_KEY_ID,
    region_name=REGION_NAME, # Must be one of: wnam, enam, weur, eeur, apac, auto
)

"""
you can get your file info before downloading
"""
@app.get("/get_file_info/{folder_name}/{file_name}")
async def get_file_info(folder_name:str, file_name:str):
    try:
        if folder_name is not None:
            # this is a wrokaround since FastAPI does not accept / characters
            # or rather sees it as @app.get request path and returns 404
            # if you have deeper folder structure either use different buckets or modify this code
            folder_name = f"{folder_name}/"
        object_information = s3.head_object(Bucket=R2_BUCKET_NAME, Key=f"{folder_name}{file_name}")
        return object_information
    except ClientError as error:
        raise error


@app.get("/download/{file_name}")
async def download(file_name:str):
    try:
        s3.download_file(Bucket=R2_BUCKET_NAME, Key=f"{file_name}", Filename=f"{file_name}" )
        object_information = s3.head_object(Bucket=R2_BUCKET_NAME, Key=f"{file_name}")
        return object_information
    except ClientError as error:
        raise error


@app.post("/upload/")
def create_upload_file(file: UploadFile):
    try:
        f_name = file.filename
        s3.upload_fileobj(file.file, R2_BUCKET_NAME, f_name)
        object_information = s3.head_object(Bucket=R2_BUCKET_NAME, Key=f"{f_name}")
        return object_information
    except ClientError as error:
        raise error

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages