> ## Documentation Index
> Fetch the complete documentation index at: https://developer.box.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Upload methods with Python

> Learn how to upload files to Box with the Python SDK by using direct upload and chunked upload, including the `upload_big_file` convenience method, manual upload sessions, preflight checks, and conflict handling.

export const SignupCTA = ({children}) => {
  return <div className="flex flex-wrap items-center gap-4 p-5 rounded-lg border border-gray-200 dark:border-gray-700 my-6" style={{
    background: "linear-gradient(135deg, rgba(0, 97, 213, 0.06), rgba(0, 97, 213, 0.02))"
  }}>
      <div className="flex-1 text-sm leading-relaxed text-gray-700 dark:text-gray-300" style={{
    minWidth: "280px"
  }}>
        {children}
      </div>
      <div className="flex flex-col items-center gap-2">
        <a href="https://account.box.com/signup/developer#ty9l3" className="signup-cta-button inline-flex items-center whitespace-nowrap px-5 py-2 text-sm font-semibold text-white no-underline">
          Get started for free
        </a>
        <a href="https://account.box.com/developers/console" className="signup-cta-login text-xs text-gray-500 dark:text-gray-400 no-underline whitespace-nowrap">
          Already have an account? Log in
        </a>
      </div>
    </div>;
};

export const MultiRelatedLinks = ({sections = []}) => {
  if (!sections || sections.length === 0) {
    return null;
  }
  return <div className="space-y-8">
      {sections.map((section, index) => <RelatedLinks key={index} title={section.title} items={section.items} />)}
    </div>;
};

export const RelatedLinks = ({title, items = []}) => {
  const getBadgeClass = badge => {
    if (!badge) return "badge-default";
    const badgeType = badge.toLowerCase().replace(/\s+/g, "-");
    return `badge-${badge === "ガイド" ? "guide" : badgeType}`;
  };
  if (!items || items.length === 0) {
    return null;
  }
  return <div className="my-8">
      {}
      <h3 className="text-sm font-bold uppercase tracking-wider mb-4">{title}</h3>

      {}
      <div className="flex flex-col gap-3">
        {items.map((item, index) => <a key={index} href={item.href} className="py-2 px-3 rounded related_link hover:bg-[#f2f2f2] dark:hover:bg-[#111827] flex items-center gap-3 group no-underline hover:no-underline border-b-0">
            {}
            <span className={`px-2 py-1 rounded-full text-xs font-semibold uppercase tracking-wide flex-shrink-0 ${getBadgeClass(item.badge)}`}>
              {item.badge}
            </span>

            {}
            <span className="text-base">{item.label}</span>
          </a>)}
      </div>
    </div>;
};

export const Link = ({href, children, className, ...props}) => {
  const localizedHref = localizeLink(href);
  return <a href={localizedHref} className={className} {...props}>
      {children}
    </a>;
};

This tutorial covers two ways to upload content to Box by using the Python SDK: <Link href="/guides/uploads/direct">direct upload</Link> and <Link href="/guides/uploads/chunked">chunked upload</Link>. 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 <Link href="/guides/uploads/check">preflight checks</Link> with conflict handling to upload new files or update existing ones.

| Method                                                     | Best for                      | Minimum size | Maximum size |
| ---------------------------------------------------------- | ----------------------------- | ------------ | ------------ |
| <Link href="/guides/uploads/direct">Direct upload</Link>   | Small files, simple workflows | No minimum   | 50 MB        |
| <Link href="/guides/uploads/chunked">Chunked upload</Link> | Large files                   | 20 MB        | No limit     |

<SignupCTA>
  A free Box developer account gives you a Developer Console, API access, and a test environment so you can start uploading files to Box and building content workflows.
</SignupCTA>

<Info>
  The code samples in this tutorial use the
  <Link href="https://github.com/box/box-python-sdk">Box Python SDK (v10)</Link>.
</Info>

## Prerequisites

* A Box application with the <Link href="/guides/api-calls/permissions-and-errors/scopes/#read-and-write-all-files-and-folders">Read and write all files and folders stored in Box</Link> scope (`root_readwrite`) enabled
* Python 3.8 or later installed on your computer
* The Box Python SDK installed (`pip install "boxsdk~=10"`)
* An authenticated <Link href="/guides/authentication">Box client</Link>

## Direct upload

To upload a file, call the `upload_file` method. For more information about the direct upload API, see
<Link href="/guides/uploads/direct/file">Upload New File</Link>.

Run a <Link href="/guides/uploads/check">preflight check</Link> 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
<Link href="/guides/uploads/direct/file-version">new version</Link>:

```python Python v10 theme={null}
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 <Link href="/guides/uploads/chunked">chunked upload</Link> for files that are
**20 MB or larger**. Every chunked upload works through an
<Link href="/guides/uploads/chunked/create-session">upload session</Link>: you
create a session,
<Link href="/guides/uploads/chunked/upload-part">upload the file in parts</Link>,
and <Link href="/guides/uploads/chunked/commit-session">commit the session</Link>
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 Python v10 theme={null}
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 Python v10 theme={null}
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 Python v10 theme={null}
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

* <Link href="https://github.com/box-community/box-python-gen-workshop/blob/main/workshops/files/files.md">Box Python SDK workshop: files and uploads</Link>
* <Link href="https://github.com/box/box-python-sdk/blob/main/docs/uploads.md">Box Python SDK: Uploads</Link>
* <Link href="https://github.com/box/box-python-sdk/blob/main/docs/chunked_uploads.md">Box Python SDK: Chunked uploads</Link>

<RelatedLinks
  title="RELATED GUIDES"
  items={[
{ label: translate("Preflight Check"), href: "/guides/uploads/check", badge: "GUIDE" },
{ label: translate("Upload New File"), href: "/guides/uploads/direct/file", badge: "GUIDE" },
{ label: translate("Upload File Version"), href: "/guides/uploads/direct/file-version", badge: "GUIDE" },
{ label: translate("Chunked Uploads"), href: "/guides/uploads/chunked", badge: "GUIDE" },
{ label: translate("Recursively upload a folder with Python"), href: "/guides/uploads/tutorials/recursive-folder-upload-python", badge: "GUIDE" }
]}
/>
