> ## 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スクリプトを使用してローカルフォルダツリーをBoxにアップロードする方法を説明します。

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

このチュートリアルでは、重複したファイル、重複したフォルダ、サイズの大きなファイルを自動的に処理するために、<Link href="/guides/uploads/direct">直接アップロード</Link>、<Link href="/guides/uploads/chunked">分割アップロード</Link>、<Link href="/guides/uploads/check">事前チェック</Link>を組み合わせた再帰的アップロードスクリプトを作成する方法を説明します。

<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>が認証済みである
* <Link href="/guides/uploads/tutorials/upload-methods-python">Pythonを使用したアップロード方法</Link>のチュートリアルが完了している (同チュートリアルで定義した`file_upload`および`file_upload_chunked`ヘルパー関数をこのチュートリアルで再利用し、アップロードロジックの重複を回避する)

## 重複したフォルダの処理

サブフォルダにアクセスする前に、そのフォルダがすでにBoxに存在しているかどうかを確認します。同名のフォルダが存在する場合は、新規フォルダを作成せずに、既存のフォルダを使用します。

```python Python v10 theme={null}
from box_sdk_gen import BoxAPIError, CreateFolderParent


def create_or_get_box_folder(client, folder_name, parent_folder_id):
    try:
        folder = client.folders.create_folder(
            folder_name, CreateFolderParent(id=parent_folder_id)
        )
    except BoxAPIError as err:
        if err.response_info.body.get("code") == "item_name_in_use":
            folder_id = err.response_info.context_info["conflicts"][0][
                "id"
            ]
            folder = client.folders.get_folder_by_id(folder_id)
        else:
            raise
    return folder
```

## フォルダの再帰的なアップロード

ローカルディレクトリツリーをたどる1つの再帰的な関数を、複数のヘルパー関数を組み合わせて作成します。各項目で、関数は次の処理を行います。

1. Box内にフォルダを作成するか、既存のフォルダを取得した後、フォルダを再帰的に処理します。
2. 直接アップロードか分割アップロードかを選択するためにファイルサイズを確認します。**20 MB以上**のファイルでは分割アップロード、それよりも小さいファイルでは直接アップロードを使用します。
3. 同名のファイルがすでに存在する場合は、アップロード方法のチュートリアルで説明したヘルパーを使用して新しいバージョンをアップロードします。

```python Python v10 theme={null}
import pathlib

MIN_CHUNKED_SIZE = 20 * 1024 * 1024  # 20 MB


def folder_upload(
    client,
    box_base_folder_id,
    local_folder_path,
    min_chunked_size=MIN_CHUNKED_SIZE,
):
    local_folder = pathlib.Path(local_folder_path)
    for item in local_folder.iterdir():
        if item.is_dir():
            new_box_folder = create_box_folder(
                client, item.name, box_base_folder_id
            )
            folder_upload(client, new_box_folder.id, item, min_chunked_size)
        else:
            if item.stat().st_size < min_chunked_size:
                file_upload(client, str(item), box_base_folder_id)
            else:
                file_upload_chunked(client, str(item), box_base_folder_id)
```

`min_chunked_size`パラメータのデフォルト値は20 MB (<Link href="/guides/uploads/chunked">分割アップロード</Link>の最小サイズ) です。このしきい値を大きくすることはできますが、小さくすることはできません。

## サンプル全体

以下のスクリプトでは、Boxクライアントを認証し、保存先フォルダを作成 (または既存フォルダを再利用) して、ローカルディレクトリのコンテンツを再帰的にアップロードします。`create_box_folder`ヘルパーを再利用して、ルートフォルダ (`"0"`) にある保存先フォルダを取得または作成しています。

```python Python v10 theme={null}
def main():
    client = get_authenticated_client()
    demo_folder = create_box_folder(client, "my-upload-folder", "0")
    folder_upload(client, demo_folder.id, "/path/to/local/folder")


if __name__ == "__main__":
    main()
```

## リソース

* <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("Upload methods with Python"), href: "/guides/uploads/tutorials/upload-methods-python", badge: "GUIDE" },
{ label: translate("Upload All Files in Folder"), href: "/guides/uploads/chunked/folder", badge: "GUIDE" },
{ label: translate("Preflight Check"), href: "/guides/uploads/check", badge: "GUIDE" },
{ label: translate("Direct Uploads"), href: "/guides/uploads/direct", badge: "GUIDE" },
{ label: translate("Chunked Uploads"), href: "/guides/uploads/chunked", badge: "GUIDE" }
]}
/>
