# Upload sessions and batches

Large files in pieces through upload sessions, a folder as a zip, save_url, and the copy, move, delete and create-folder batches with their job checks.

Upload sessions move a file in pieces, and batches and `save_url` run as async jobs that your code checks for completion. Boot the simulator as in the Quickstart, then start a session with the first piece:

```bash
H='Authorization: Bearer sl.placeholder'
J='Content-Type: application/json'
O='Content-Type: application/octet-stream'
S=$(curl -s "$RYSTIC_URL/2/files/upload_session/start" -H "$H" -H "$O" -H 'Dropbox-API-Arg: {"close":false}' --data-binary 'hello ' | jq -r .session_id)
curl -s "$RYSTIC_URL/2/files/upload_session/append_v2" -H "$H" -H "$O" -H "Dropbox-API-Arg: {\"cursor\":{\"session_id\":\"$S\",\"offset\":6},\"close\":false}" --data-binary 'world'
# -> null
curl -s "$RYSTIC_URL/2/files/upload_session/finish" -H "$H" -H "$O" -H "Dropbox-API-Arg: {\"cursor\":{\"session_id\":\"$S\",\"offset\":11},\"commit\":{\"path\":\"/big.txt\",\"mode\":\"add\"}}" --data-binary '' | jq -c '{name, size}'
# -> {"name":"big.txt","size":11}
curl -s "$RYSTIC_URL/2/files/download" -H "$H" -H 'Dropbox-API-Arg: {"path":"/big.txt"}'
# -> hello world
```

The argument rides in `Dropbox-API-Arg` and the bytes in the body. A copy, move or delete batch returns an `async_job_id`, and its check route reports the job:

```bash
JOB=$(curl -s "$RYSTIC_URL/2/files/copy_batch_v2" -H "$H" -H "$J" -d '{"entries":[{"from_path":"/notes.md","to_path":"/notes-copy.md"}]}' | jq -r .async_job_id)
curl -s "$RYSTIC_URL/2/files/copy_batch/check_v2" -H "$H" -H "$J" -d "{\"async_job_id\":\"$JOB\"}" | jq -c .
# -> {".tag":"in_progress"}
curl -s "$RYSTIC_URL/2/files/copy_batch/check_v2" -H "$H" -H "$J" -d "{\"async_job_id\":\"$JOB\"}" | jq -c '{status: .[".tag"], copied: [.entries[].success.name]}'
# -> {"status":"complete","copied":["notes-copy.md"]}
```

### Upload sessions

A session holds the bytes it has taken so far, and each append names the offset it starts at:

| Request | Result |
|---|---|
| `upload_session/append_v2` whose `cursor.offset` differs from the bytes the session holds | 409 `incorrect_offset` with `correct_offset`; the session keeps what it had |
| a second `finish` at the held offset | commits the bytes again |
| an append after `finish` | 409 `closed` |

`start_batch`, `append_batch` and `finish_batch_v2` do the same for many sessions at once.

**Differs from Dropbox:** a session commits at most 150 MiB in all, where Dropbox takes up to 2 TiB. Past that, an append returns 409 `too_large`.

### Async jobs and their checks

`save_url`, `copy_batch_v2`, `move_batch_v2` and `delete_batch` return an `async_job_id`. The job's check returns `in_progress` on the first read and `complete` on the next, or once the clock has moved two seconds past the launch. `create_folder_batch` returns `complete` inline.

Each entry of a copy, move or delete batch runs as `copy_v2`, `move_v2` or `delete_v2` would run it. A copied file downloads its bytes under its own `rev`, and a folder goes with everything beneath it. A file's members and shared links follow it or go with it. Every entry carries its own `success` or `failure`, so a batch with one bad path completes with that entry failed and the rest done.

### save_url

A completed `save_url` job has written a file at the job's path, which `get_metadata`, `list_folder` and `download` read back.

**Differs from Dropbox:** the simulator fetches nothing from the URL. The file's bytes are a placeholder derived from it.

### Folders as zip files

`files/download_zip` returns a folder as `application/zip`, with its metadata in `Dropbox-API-Result`.

---

Source: https://www.rystic.ai/docs/simulators/dropbox/features/upload-sessions-and-batches · Markdown: https://www.rystic.ai/docs/simulators/dropbox/features/upload-sessions-and-batches.md
