2 min read
Dropbox download to your VM
**`Published: Jun 2021

Handy script to download all your business from dropbox

This script had to undergo a lot of iterations, it failed a lot of times after download for hours on length,

import dropbox
import os
from concurrent.futures import ThreadPoolExecutor
from time import sleep

# Initialize Dropbox client with refresh token and app key for automatic token refresh
dbx = dropbox.Dropbox(
    oauth2_refresh_token="<>",
    app_key="<>",
    app_secret="<>"
)

# Function to log locked paths
def log_locked_path(path):
    with open("locked_paths.log", "a") as log_file:
        log_file.write(f"Locked: {path}\n")

# Function to download a single file with retry mechanism
def download_file(entry, local_path):
    local_file_path = os.path.join(local_path, entry.name)
    max_retries = 3
    for i in range(max_retries):
        try:
            metadata, res = dbx.files_download(path=entry.path_lower)
            with open(local_file_path, "wb") as f:
                for chunk in res.iter_content(chunk_size=1024):
                    if chunk:
                        f.write(chunk)
            print(f"Downloaded {entry.name} to {local_file_path}")
            return  # Successful download, so exit the loop
        except (dropbox.exceptions.ApiError, Exception) as e:  # Catching generic Exception to include network errors
            print(f"An error occurred: {e}. Retrying...")
            sleep(2 ** i)  # Exponential backoff
    log_locked_path(f"Failed after {max_retries} retries: {entry.path_lower}")  # Log the failure after max retries

# Function to download files recursively
def download_files(folder_path, local_path):
    try:
        entries = dbx.files_list_folder(folder_path).entries
    except dropbox.exceptions.ApiError as e:
        if 'locked' in str(e.error):
            log_locked_path(folder_path)
            print(f"Skipping locked folder: {folder_path}")
            return
        else:
            raise e

    with ThreadPoolExecutor(max_workers=3) as executor:  # Limit to 3 threads
        for entry in entries:
            if isinstance(entry, dropbox.files.FileMetadata):
                # It's a file, download it in a new thread
                executor.submit(download_file, entry, local_path)
            elif isinstance(entry, dropbox.files.FolderMetadata):
                # It's a folder, recurse into it
                new_folder_path = os.path.join(local_path, entry.name)
                os.makedirs(new_folder_path, exist_ok=True)
                download_files(entry.path_lower, new_folder_path)

# Set your Dropbox folder and local folder paths
dropbox_folder_path = ""  # Root folder in Dropbox
local_folder_path = "/home/ubuntu/dropbox"  # Local folder path on EC2

# Start the download
download_files(dropbox_folder_path, local_folder_path)