> ## 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.

> Python SDKを使用してBoxにファイルをアップロードする方法について、直接アップロードと分割アップロードをそれぞれ説明します。`upload_big_file`という便利なメソッド、手動のアップロードセッション、事前チェック、競合処理も取り上げます。

# Pythonを使用したアップロード方法

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>;
};

このチュートリアルでは、Python SDKを使用してBoxにコンテンツをアップロードする2つの方法 (<Link href="/guides/uploads/direct">直接アップロード</Link>と<Link href="/guides/uploads/chunked">分割アップロード</Link>) を取り上げます。分割アップロードには、SDKの便利なメソッドを使う方法と、アップロードセッションを自分で管理する方法があります。各方法の仕組みと、<Link href="/guides/uploads/check">事前チェック</Link>と競合処理を組み合わせて新規ファイルをアップロードしたり、既存のファイルを更新したりする方法について説明します。

| メソッド                                                 | 最適な用途                   | 最小サイズ | 最大サイズ |
| ---------------------------------------------------- | ----------------------- | ----- | ----- |
| <Link href="/guides/uploads/direct">直接アップロード</Link>  | サイズの小さいファイル、シンプルなワークフロー | 下限なし  | 50 MB |
| <Link href="/guides/uploads/chunked">分割アップロード</Link> | サイズの大きいファイル             | 20 MB | 上限なし  |

<SignupCTA>
  無料のDeveloperアカウントを作成すると、開発者コンソール、APIアクセス、テスト環境を利用できるようになり、Boxへのファイルのアップロードとコンテンツワークフローの構築を開始できます。
</SignupCTA>

<Info>
  このチュートリアルのコードサンプルでは、<Link href="https://github.com/box/box-python-sdk">Box Python SDK (v10)</Link> を使用しています。
</Info>

## 前提条件

* Boxアプリケーションで \[<Link href="/guides/api-calls/permissions-and-errors/scopes/#read-and-write-all-files-and-folders">Boxに格納されているすべてのファイルとフォルダの読み取りと書き込み</Link>] スコープ (`root_readwrite`) が有効になっている
* コンピュータにPython 3.8以降がインストールされている
* Box Python SDKがインストールされている (`pip install "boxsdk~=10"`)
* <Link href="/guides/authentication">Boxクライアント</Link>が認証済みである

## 直接アップロード

ファイルをアップロードするには、`upload_file`メソッドを呼び出します。直接アップロードAPIの詳細については、<Link href="/guides/uploads/direct/file">新しいファイルのアップロード</Link>を参照してください。

最初に<Link href="/guides/uploads/check">事前チェック</Link>を実行します。同名のファイルがすでに存在する場合は、エラーレスポンスに競合ファイルのIDが含まれます。その名前のファイルのコンテンツを上書きしたくない場合は、名前を変更して新規ファイルとしてアップロードします。以下のサンプルでは、ファイルのコンテンツを上書きする必要があると想定し、そのIDを使用して<Link href="/guides/uploads/direct/file-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]
```

フォルダで`upload_file`を呼び出すと新規ファイルが作成されます。既存ファイルで`upload_file_version`を呼び出すと新しいバージョンがアップロードされます。

## 分割アップロード

**20 MB以上**のファイルには<Link href="/guides/uploads/chunked">分割アップロード</Link>を使用します。各分割アップロードは<Link href="/guides/uploads/chunked/create-session">アップロードセッション</Link>を通じて行われます。アップロードセッションでは、セッションを作成して、<Link href="/guides/uploads/chunked/upload-part">パーツ単位でファイルをアップロード</Link>し、<Link href="/guides/uploads/chunked/commit-session">セッションをコミット</Link>することでファイルを確定します。これには、2つの方法があります。

* **便利なメソッド**: `upload_big_file`を使用すると、3つのステップすべてが自動で行われます。
* **手動のアップロードセッション**: 詳細な制御が必要な場合は、セッションの作成、各パーツのアップロード、コミットを自分で行います。

### 便利なメソッド

`upload_big_file`メソッドを使用すると、パーツ単位でファイルが自動的にアップロードされます。アップロード開始前に名前の競合を処理できるよう、最初に事前チェックを実行します。同名のファイルがすでに存在する場合は、`upload_chunked_file`によって既存ファイル用のセッションが作成され、次のセクションで示すように`upload_file_via_session`ヘルパーによって新しいバージョンがアップロードされます。

```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
        )
```

### 手動のアップロードセッション

アップロードを詳細に制御するには、自分でセッションを管理します。自分が渡したセッションについて、`upload_file_via_session`ヘルパーによってすべてのパートがアップロードされ、セッションがコミットされます。

```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_file_upload_session`を使用して新しいファイルを作成します。同名のファイルがすでに存在する場合、`upload_file_manual`は`create_file_upload_session_for_existing_file`にフォールバックして新しいバージョンをアップロードします。

```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
    )
```

## リソース

* <Link href="https://github.com/box-community/box-python-gen-workshop/blob/main/workshops/files/files.md">Box Python SDKワークショップ: ファイルとアップロード</Link>
* <Link href="https://github.com/box/box-python-sdk/blob/main/docs/uploads.md">Box Python SDK: アップロード</Link>
* <Link href="https://github.com/box/box-python-sdk/blob/main/docs/chunked_uploads.md">Box Python SDK: 分割アップロード</Link>

<RelatedLinks
  title="関連するガイド"
  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" }
]}
/>
