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

# パーツのアップロード

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

<RelatedLinks
  title="必須のガイド"
  items={[
{ label: translate("Create Upload Session"), href: "/guides/uploads/chunked/create-session", badge: "GUIDE" }
]}
/>

大きいファイルをアップロードする際は、そのファイルを小さいパーツに分割し、パーツのアップロードAPIを使用してそれらのパーツをアップロードできます。

## アップロードセッションの作成

最初に<Link href="/guides/uploads/chunked/create-session">アップロードセッションを作成</Link>します。結果のオブジェクトにより、各パーツのサイズとアップロードするパーツの数が定義されます。

```json theme={null}
{
  "id": "F971964745A5CD0C001BBE4E58196BFD",
  "type": "upload_session",
  "session_expires_at": "2012-12-12T10:53:43-08:00",
  "part_size": 1024,
  "total_parts": 1000,
  "num_parts_processed": 455,
  "session_endpoints": {
    "upload_part": "https://upload.box.com/api/2.0/files/upload_sessions/F971964745A5CD0C001BBE4E58196BFD",
    "commit": "https://upload.box.com/api/2.0/files/upload_sessions/F971964745A5CD0C001BBE4E58196BFD/commit",
    "abort": "https://upload.box.com/api/2.0/files/upload_sessions/F971964745A5CD0C001BBE4E58196BFD",
    "list_parts": "https://upload.box.com/api/2.0/files/upload_sessions/F971964745A5CD0C001BBE4E58196BFD/parts",
    "status": "https://upload.box.com/api/2.0/files/upload_sessions/F971964745A5CD0C001BBE4E58196BFD",
    "log_event": "https://upload.box.com/api/2.0/files/upload_sessions/F971964745A5CD0C001BBE4E58196BFD/log"
  }
}
```

## ファイルの分割

ファイルをアップロードするパーツに分割します。コマンドラインを使用する場合は、`split`コマンドを使用します。

```bash theme={null}
split -b <PART_SIZE> <FILE_NAME> <YOUR_PART_NAME>
```

例:

```bash theme={null}
split -b 8388608 video.mp3 videopart
```

これにより、ファイルが複数のファイルに分割されます。

## SHAダイジェストの取得

`SHA`ダイジェストの値を取得するには、次のopenSSLコマンドを使用して、ファイルのパーツをエンコードします。

```bash theme={null}
openssl sha1 -binary <FILE_PART_NAME> | base64
```

例:

```bash theme={null}
openssl sha1 -binary videoparta | base64
```

その結果、Base64でエンコードされたメッセージがアップロードの検証に使用されます。

## パーツのアップロード

アップロードするパーツのデータをアップロードします。その際、パーツのバイト範囲と、コンテンツを適切にアップロードするための`SHA`ダイジェストを指定します。

<CodeGroup>
  ```sh cURL theme={null}
  curl -i -X PUT "https://upload.box.com/2.0/files/upload_sessions/F971964745A5CD0C001BBE4E58196BFD" \
       -H "authorization: Bearer <ACCESS_TOKEN>" \
       -H "digest: sha=fpRyg5eVQletdZqEKaFlqwBXJzM=" \
       -H "content-range: bytes 8388608-16777215/445856194" \
       -H "content-type: application/octet-stream" \
       --data-binary @<FILE_NAME>
  ```

  ```typescript Node/TypeScript v10 theme={null}
  await client.chunkedUploads.uploadFilePart(
    acc.uploadSessionId,
    generateByteStreamFromBuffer(chunkBuffer),
    {
      digest: digest,
      contentRange: contentRange,
    } satisfies UploadFilePartHeadersInput,
  );
  ```

  ```python Python v10 theme={null}
  client.chunked_uploads.upload_file_part(
      acc.upload_session_id,
      generate_byte_stream_from_buffer(chunk_buffer),
      digest,
      content_range,
  )
  ```

  ```cs .NET v10 theme={null}
  await client.ChunkedUploads.UploadFilePartAsync(uploadSessionId: acc.UploadSessionId, requestBody: Utils.GenerateByteStreamFromBuffer(buffer: chunkBuffer), headers: new UploadFilePartHeaders(digest: digest, contentRange: contentRange));
  ```

  ```swift Swift v10 theme={null}
  try await client.chunkedUploads.uploadFilePart(uploadSessionId: acc.uploadSessionId, requestBody: Utils.generateByteStreamFromBuffer(buffer: chunkBuffer), headers: UploadFilePartHeaders(digest: digest, contentRange: contentRange))
  ```

  ```java Java v10 theme={null}
  client.getChunkedUploads().uploadFilePart(acc.getUploadSessionId(), generateByteStreamFromBuffer(chunkBuffer), new UploadFilePartHeaders(digest, contentRange))
  ```

  ```java Java v5 theme={null}
  //Reading a large file
  FileInputStream fis = new FileInputStream("My_Large_File.txt");
  //Create the digest input stream to calculate the digest for the whole file.
  DigestInputStream dis = new DigestInputStream(fis, digest);

  List<BoxFileUploadSessionPart> parts = new ArrayList<BoxFileUploadSessionPart>();

  //Get the part size. Each uploaded part should match the part size returned as part of the upload session.
  //The last part of the file can be less than part size if the remaining bytes of the last part is less than
  //the given part size
  long partSize = sessionInfo.getPartSize();
  //Start byte of the part
  long offset = 0;
  //Overall of bytes processed so far
  long processed = 0;
  while (processed < fileSize) {
      long diff = fileSize - processed;
      //The size last part of the file can be less than the part size.
      if (diff < partSize) {
          partSize = diff;
      }

      //Upload a part. It can be uploaded asynchorously
      BoxFileUploadSessionPart part = session.uploadPart(dis, offset, (int)partSize, fileSize);
      parts.add(part);

      //Increase the offset and proceesed bytes to calculate the Content-Range header.
      processed += partSize;
      offset += partSize;
  }
  ```

  ```python Python v4 theme={null}
  upload_session = client.upload_session('11493C07ED3EABB6E59874D3A1EF3581')
  offset = upload_session.part_size * 3
  total_size = 26000000
  part_bytes = b'abcdefgh'
  part = upload_session.upload_part_bytes(part_bytes, offset, total_size)
  print(f'Successfully uploaded part ID {part["part_id"]}')
  ```

  ```javascript Node v4 theme={null}
  // Upload the part starting at byte offset 8388608 to upload session '93D9A837B45F' with part ID 'feedbeef'
  client.files.uploadPart('93D9A837B45F', part, 8388608, 2147483648, {part_id: 'feedbeef'}, callback);
  ```
</CodeGroup>

### コンテンツの範囲

各パーツのサイズは、作成したアップロードセッションで指定されているパーツサイズとまったく同じサイズである必要があります。ただし、ファイルの最後のパーツは小さくなる可能性があるため、例外となります。`Content-Range`パラメータの定義は、次のパターンに従います。

```yaml theme={null}
-H "Content-Range: bytes <LOWER_BOUND>-<HIGHER_BOUND>/<TOTAL_SIZE>"
```

`Content-Range`の値を指定する際は、以下の点に注意してください。

* 各パーツのバイト範囲の下限は、パーツサイズの倍数にする必要があります。
* 上限は、パーツサイズの倍数から1を引いた値にする必要があります。

たとえば、パーツサイズが`8388608`の場合、最初の2つのパーツのコンテンツの範囲は次のようになります。

```yaml theme={null}
-H "Content-Range: bytes 0-8388607/32127641" \ ## first part
-H "Content-Range: bytes 8388608-16777215/32127641" \ ## second part
```

## レスポンス

各アップロードの後、結果のレスポンスには、アップロードされたパーツの`ID`と`SHA`が含まれます。

```json theme={null}
{
  "part_id": "6F2D3486",
  "offset": 16777216,
  "size": 3222784,
  "sha1": "134b65991ed521fcfe4724b7d814ab8ded5185dc"
}
```

<Warning>
  すべてのパーツアップロードのすべてのJSONレスポンスは、<Link href="/guides/uploads/chunked/commit-session">セッションのコミット</Link>に必要なため、保持してください。
</Warning>

## 範囲の重複

パーツアップロードのリクエストがエラーコード`range_overlaps_existing_part`で失敗するのは、アプリケーションがファイルの分割に失敗し、すでにコンテンツがアップロードされている範囲にパーツをアップロードしようとしたことが原因です。アプリケーションでは、この最後のパーツがセッションに継続されなかったと想定する必要があります。

## 並行アップロード

パーツは並行してアップロードできますが、可能な限り順番にアップロードするようにしてください。バイトオフセットが小さいパーツは、バイトオフセットが大きいパーツより先にアップロードする必要があります。

推奨されるのは、バイトオフセット順に並べたパーツのキューから、3～5個のパーツを並行してアップロードする方法です。パーツのアップロードが失敗した場合は、さらにパーツをアップロードする前に、失敗したアップロードを再試行してください。

<RelatedLinks
  title="関連するAPI"
  items={[
{ label: translate("Upload part of file"), href: "/reference/put-files-upload-sessions-id", badge: "PUT" }
]}
/>

<RelatedLinks
  title="関連するガイド"
  items={[
{ label: translate("Commit Upload Session"), href: "/guides/uploads/chunked/commit-session", badge: "GUIDE" }
]}
/>
