Do you use Backblaze B2 and want an easy way to upload files from the command line? Python not only makes this easy, but the Click library makes it enjoyable.

Use case

I store a lot of data on B2. When I post pictures, GIFs, or videos to my blog, I upload them there. I wanted a quick way to upload files with little thought while keeping them organized. The same tool could also back up local data or store files on demand.

Environment

  • Python 3.12.2
  • Click 8.1.7
  • b2sdk 1.31.0

Implementation

Start with the imports and constants. In a real tool, load these values from environment variables or a secrets manager.

upload_to_b2.py
import click
from datetime import datetime
import os
from b2sdk.v2 import InMemoryAccountInfo, B2Api

B2_BUCKET = 'Bucket'
B2_KEY = 'Key'
B2_APP_KEY = 'App Key'
Do not use the Master Application Key. Create a scoped application key that can access only the intended bucket.

Click validates the path and provides optional year, month, and slug values. Defaults keep the common case short.

upload_to_b2.py
@click.command()
@click.argument('file_to_upload', type=click.Path(exists=True))
@click.option('--year', default=datetime.now().year, help='Year of post')
@click.option('--month', default=datetime.now().strftime("%m"), help='Month of post')
@click.option('--slug', help='Folder or post slug')
def main(year, month, slug, file_to_upload):
    click.echo(
        f"{click.style('Year:', bold=True)} {year}, "
        f"{click.style('Month:', bold=True)} {month}, "
        f"{click.style('Slug:', bold=True)} {slug}"
    )

Next, authorize the B2 client, derive the destination path, upload the file, and print its final URL.

upload_to_b2.py
    info = InMemoryAccountInfo()
    b2_api = B2Api(info)
    b2_api.authorize_account("production", B2_KEY, B2_APP_KEY)
    bucket = b2_api.get_bucket_by_name(B2_BUCKET)

    original_file_name = os.path.basename(file_to_upload)
    destination_path = f"{year}/{month}/{slug}/{original_file_name}"

    bucket.upload_local_file(
        local_file=file_to_upload,
        file_name=destination_path,
    )

    click.echo(
        f"File uploaded to B2: https://bucket.website.com/"
        f"{year}/{month}/{slug}/{original_file_name}"
    )

if __name__ == '__main__':
    main()

Demo

Terminal
$ python upload_to_b2.py --year=2024 --month=02 --slug=demo ~/Downloads/demo.png
Year: 2024, Month: 02, Slug: demo
File uploaded to B2: https://bucket.website.com/2024/02/demo/demo.png

Additional reading