Skip to main content
This tutorial covers two ways to upload content to Box by using the Python SDK: and . For chunked upload, you can use the SDK convenience method or manage the upload session yourself. Learn how each method works and how to combine with conflict handling to upload new files or update existing ones.
MethodBest forMinimum sizeMaximum size
Small files, simple workflowsNo minimum50 MB
Large files20 MBNo limit
The code samples in this tutorial use the .

Prerequisites

  • A Box application with the scope (root_readwrite) enabled
  • Python 3.8 or later installed on your computer
  • The Box Python SDK installed (pip install "boxsdk~=10")
  • An authenticated

Direct upload

To upload a file, call the upload_file method. For more information about the direct upload API, see . Run a first. If a file with the same name already exists, the error response includes the conflicting file ID. If you don’t want to override the content of the file with that name, change the name and upload it as a new file. The sample below assumes you want to override the file content, so it uses that ID to upload a :
Python v10
import os

from box_sdk_gen import (
    BoxAPIError,
    PreflightFileUploadCheckParent,
    UploadFileAttributes,
    UploadFileAttributesParentField,
    UploadFileVersionAttributes,
)


def upload_file_or_file_version(client, file_path, folder_id):
    file_size = os.path.getsize(file_path)
    file_name = os.path.basename(file_path)

    with open(file_path, "rb") as file_stream:
        try:
            client.uploads.preflight_file_upload_check(
                name=file_name,
                size=file_size,
                parent=PreflightFileUploadCheckParent(id=folder_id),
            )
            files = client.uploads.upload_file(
                UploadFileAttributes(
                    name=file_name,
                    parent=UploadFileAttributesParentField(id=folder_id),
                ),
                file_stream,
            )
            return files.entries[0]
        except BoxAPIError as err:
            if err.response_info.code != "item_name_in_use":
                raise
            file_id = err.response_info.context_info["conflicts"]["id"]
            file_stream.seek(0)
            files = client.uploads.upload_file_version(
                file_id,
                UploadFileVersionAttributes(name=file_name),
                file_stream,
            )
            return files.entries[0]
Calling upload_file on a folder creates a new file. Calling upload_file_version on an existing file uploads a new version.

Chunked upload

Use for files that are 20 MB or larger. Every chunked upload works through an : you create a session, , and to finalize the file. You have two options:
  • Convenience method: upload_big_file runs all three steps for you.
  • Manual upload session: create the session, upload each part, and commit it yourself when you need full control.

Convenience method

The upload_big_file method uploads the file in parts automatically. Run a preflight check first so that you can handle name conflicts before you start the upload. When a file with the same name already exists, upload_chunked_file creates a session for the existing file and uploads a new version with the upload_file_via_session helper shown in the next section.
Python v10
import os

from box_sdk_gen import BoxAPIError, PreflightFileUploadCheckParent


def upload_chunked_file(client, file_path, folder_id):
    file_size = os.path.getsize(file_path)
    file_name = os.path.basename(file_path)
    parent = PreflightFileUploadCheckParent(id=folder_id)

    try:
        client.uploads.preflight_file_upload_check(
            name=file_name,
            size=file_size,
            parent=parent,
        )
        with open(file_path, "rb") as file_stream:
            return client.chunked_uploads.upload_big_file(
                file_stream, file_name, file_size, folder_id
            )

    except BoxAPIError as err:
        if err.response_info.code != "item_name_in_use":
            raise

        file_id = err.response_info.context_info["conflicts"]["id"]
        upload_session = (
            client.chunked_uploads.create_file_upload_session_for_existing_file(
                file_id, file_size, file_name
            )
        )
        return upload_file_via_session(
            client, file_path, file_size, upload_session
        )

Manual upload session

For full control over the upload, manage the session yourself. The upload_file_via_session helper uploads every part and commits the session for a session you pass in:
Python v10
import base64
import hashlib
from io import BytesIO

from box_sdk_gen import UploadPart


def upload_file_via_session(client, file_path, file_size, upload_session):
    file_sha1 = hashlib.sha1()
    parts: list[UploadPart] = []

    upload_part_url = upload_session.session_endpoints.upload_part
    commit_url = upload_session.session_endpoints.commit

    with open(file_path, "rb") as file_stream:
        part_size = upload_session.part_size
        for part_num in range(upload_session.total_parts):
            offset = part_num * part_size
            remaining = file_size - offset
            chunk_size = min(part_size, remaining)
            chunk = file_stream.read(chunk_size)

            part_sha1 = hashlib.sha1(chunk).digest()
            digest = f"sha={base64.b64encode(part_sha1).decode()}"
            content_range = (
                f"bytes {offset}-{offset + len(chunk) - 1}/{file_size}"
            )

            uploaded_part = client.chunked_uploads.upload_file_part_by_url(
                upload_part_url,
                BytesIO(chunk),
                digest,
                content_range,
            )
            parts.append(uploaded_part.part)
            file_sha1.update(chunk)

    content_sha1 = file_sha1.digest()
    digest = f"sha={base64.b64encode(content_sha1).decode()}"
    files = client.chunked_uploads.create_file_upload_session_commit_by_url(
        commit_url, parts, digest
    )
    return files.entries[0]
Create the session before calling the helper. Run a preflight check first, then use create_file_upload_session for a new file. When a file with the same name already exists, upload_file_manual falls back to create_file_upload_session_for_existing_file to upload a new version:
Python v10
import os

from box_sdk_gen import BoxAPIError, PreflightFileUploadCheckParent


def upload_file_manual(client, file_path, folder_id):
    file_size = os.path.getsize(file_path)
    file_name = os.path.basename(file_path)
    parent = PreflightFileUploadCheckParent(id=folder_id)

    try:
        client.uploads.preflight_file_upload_check(
            name=file_name,
            size=file_size,
            parent=parent,
        )
        upload_session = client.chunked_uploads.create_file_upload_session(
            folder_id, file_size, file_name
        )
    except BoxAPIError as err:
        if err.response_info.code != "item_name_in_use":
            raise

        file_id = err.response_info.context_info["conflicts"]["id"]
        upload_session = (
            client.chunked_uploads.create_file_upload_session_for_existing_file(
                file_id, file_size, file_name
            )
        )

    return upload_file_via_session(
        client, file_path, file_size, upload_session
    )

Resources