Upload Part

Upload Part

To upload a part, first create an upload session. The resulting object defines the size of each part and the number of parts to upload.

Then, upload the bytes for the part you want to upload, specifying the byte range for the part, as well as the SHA digest to ensure the content is uploaded correctly.

cURL
curl -X PUT https://upload.box.com/api/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>
Java
//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
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('Successfully uploaded part ID {0}'.format(part['part_id']))
Node
// 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);

Part Size

Each part’s size must be exactly equal in size to the part size specified in the upload session that was created. One exception is the last part of the file, as this is allowed to be smaller.

Tip

As a result, the lower bound of each part's byte range should be a multiple of the part size.

Response

After each upload, the resulting response includes the ID and SHA of the part uploaded.

{
  "part_id": "6F2D3486",
  "offset": 16777216,
  "size": 3222784,
  "sha1": "134b65991ed521fcfe4724b7d814ab8ded5185dc"
}

The client is recommended to log keep all the JSON responses from all part uploads as they are needed to commit the session.

Range Overlap

If a part upload request fails with any error code range_overlaps_existing_part then the application made a mistake in cutting up the file into parts and tried to upload a part into a range that already had content uploaded for it. The application should assume that this last part was not persisted to the session.

Parallel uploads

Although parts can be uploaded in parallel, parts should be uploaded in order as much as is possible. Parts with a lower byte offset should be uploaded before parts with a higher byte offset.

The recommended approach is to upload 3 to 5 parts in parallel from a queue of parts, ordered by byte offset. If a part upload fails, it should be retried before later parts are uploaded.