# How to Upload Large Files with Microsoft Graph API Using Resumable Sessions

The Microsoft Graph large file upload API uses resumable upload sessions to transfer files up to `250 GB` by slicing binary data into sequential byte ranges aligned to `320 KiB` increments. Microsoft Graph simple PUT calls cap out at 250 MB and drop partial transfers during transient socket resets, forcing clients to restart from byte zero. Resumable upload sessions provide dedicated temporary endpoints that track committed fragments across OneDrive and SharePoint.

Source: https://fast.io/resources/microsoft-graph-api-upload-large-file/
Author: [Derek Labian](https://fast.io/authors/derek-labian/)
Last reviewed: 2026-10-11

## Why Direct PUT Uploads Fail for Large Files in Microsoft Graph

Direct single-request HTTP uploads collapse under real-world network conditions whenever file payloads exceed modest sizes. Microsoft Graph simple PUT calls cap out at 250 MB, rejecting any payload exceeding this single-request limit with a `413 Payload Too Large` status code. Even well below that ceiling, uploading files through a single atomic request across unstable connections introduces severe reliability hazards. When developer tools, ingestion pipelines, or automated background workers attempt to stream multi-gigabyte files through a standard HTTP PUT, any socket reset or transient network timeout terminates the connection immediately. Because the server treats the request as an atomic unit, it discards every previously transmitted byte, requiring the client to restart the entire transfer from byte zero.

The Microsoft Graph large file upload API uses resumable upload sessions to transfer files up to `250 GB` by slicing binary data into sequential byte ranges aligned to `320 KiB` increments. Instead of keeping a single long-lived TCP socket open across the entire transfer duration, your application establishes a session, receives a temporary pre-authenticated upload endpoint, and transmits the binary payload in discrete, manageable chunks. If a packet drop or socket reset interrupts chunk transmission, the client queries the upload session status, inspects the missing byte ranges, and resumes transmission from the exact point of interruption.

### Why Direct PUT Requests Break at Scale

Simple uploads in Microsoft Graph send the raw binary payload directly to `PUT /drives/{drive-id}/items/{parent-id}:/{filename}:/content`, as outlined in the [Microsoft Graph driveItem put content documentation](https://learn.microsoft.com/en-us/graph/api/driveitem-put-content?view=graph-rest-1.0). While suitable for small documents, configuration files, and lightweight images, this route introduces three architectural constraints:

1. **Payload Size Hard Ceiling:** Single-request PUT requests cannot exceed `250 MB`. Larger files, such as container images, high-resolution media, raw database dumps, or virtual machine images, are rejected by the API gateway before processing begins.
2. **Absence of Socket Resumability:** The simple PUT endpoint lacks state-tracking infrastructure for in-flight streams. If a connection drops after sending most of an in-flight file, the API drops the socket and discards the received buffer. The client application has no mechanism to resume transmission from the point of interruption.
3. **Gateway and Reverse Proxy Timeouts:** Enterprise networks, firewalls, and corporate reverse proxies enforce maximum idle connection limits and socket lifetimes. Uploading a massive file over an uplink with variable bandwidth frequently breaches these timeouts, triggering intermediate proxy drops.

### Core Lifecycle of a Graph Resumable Session

To transfer large files reliably to OneDrive for Business, personal OneDrive, or SharePoint Online document libraries, applications follow a structured four-stage resumable sequence:

1. **Session Creation:** Send an authenticated `POST` request to `createUploadSession` targeting the desired drive path. The response supplies an opaque, pre-authenticated `uploadUrl` and an expiration timestamp.
2. **Chunk Geometry Calculation:** Partition the local file into sequential byte segments. Each intermediate fragment size must align to an exact multiple of `320 KiB`.
3. **Sequential Fragment Upload:** Transmit each chunk via HTTP `PUT` requests to the temporary `uploadUrl`. In this stage, the client specifies the exact byte range in the `Content-Range` header and omits the standard `Authorization` bearer token.
4. **Commit and Completion Verification:** The server returns `202 Accepted` containing the next expected byte ranges after each intermediate chunk. When the final byte chunk is accepted, Microsoft Graph commits the file into the document library and returns a `201 Created` or `200 OK` response with full item metadata.

## How to Upload Large Files with Microsoft Graph API createUploadSession

Initiating an upload session requires an authenticated `POST` request to the Microsoft Graph API, as specified in the official [Microsoft Graph createUploadSession documentation](https://learn.microsoft.com/en-us/graph/api/driveitem-createuploadsession?view=graph-rest-1.0). The specific URL path depends on whether you are writing to a user drive, a shared document library in SharePoint, or an existing item.

### Target Endpoints Across Drive Hierarchies

Select the endpoint path corresponding to your storage location:

* **Current User OneDrive:** `POST https://graph.microsoft.com/v1.0/me/drive/items/{parent-item-id}:/{filename}:/createUploadSession`
* **Specific User Drive by ID:** `POST https://graph.microsoft.com/v1.0/users/{user-id}/drive/items/{parent-item-id}:/{filename}:/createUploadSession`
* **SharePoint Document Library:** `POST https://graph.microsoft.com/v1.0/sites/{site-id}/drive/items/{parent-item-id}:/{filename}:/createUploadSession`
* **Microsoft 365 Group Drive:** `POST https://graph.microsoft.com/v1.0/groups/{group-id}/drive/items/{parent-item-id}:/{filename}:/createUploadSession`
* **Direct Drive Target by ID:** `POST https://graph.microsoft.com/v1.0/drives/{drive-id}/items/{parent-item-id}:/{filename}:/createUploadSession`

If you intend to overwrite the binary content of an existing file rather than create a new item under a folder, target the item ID directly:

`POST https://graph.microsoft.com/v1.0/drives/{drive-id}/items/{existing-item-id}/createUploadSession`

### Request Configuration and Conflict Behavior

The session creation request requires an `Authorization: Bearer {token}` header containing an access token with delegated or application permissions such as `Files.ReadWrite` or `Files.ReadWrite.All`.

While the request body is optional, production implementations should pass an `item` object specifying the desired conflict resolution strategy using the `@microsoft.graph.conflictBehavior` parameter:

```json
{
  "item": {
    "@microsoft.graph.conflictBehavior": "rename",
    "name": "large-dataset-archive.tar.gz",
    "description": "Quarterly telemetry export"
  },
  "deferCommit": false
}
```

The conflict behavior property accepts three values:
* `fail`: Rejects the upload session if an item with the same name already exists in the target folder.
* `replace`: Overwrites the existing file upon successful completion of the upload session.
* `rename`: Appends a numerical suffix to the filename if a collision exists, preventing unintentional data loss.

### Inspecting the Session Creation Response

When the request succeeds, Microsoft Graph responds with `200 OK` and returns a session descriptor:

```json
{
  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#microsoft.graph.uploadSession",
  "uploadUrl": "https://sn3302.up.1drv.com/up/fe6143a4933a7e/.../upload_session_token",
  "expirationDateTime": "2026-10-12T14:30:00.000Z",
  "nextExpectedRanges": [
    "0-"
  ]
}
```

The returned `uploadUrl` is an opaque, pre-authenticated URL. It embeds the necessary routing and credential signatures within its query parameters. Applications must persist this URL for the duration of the upload process. The `expirationDateTime` field indicates when the session will be discarded by Microsoft Graph, typically giving clients up to `24 hours` to complete the file transfer.

## How to Calculate Chunk Geometry and Transmit Byte Ranges

Once your application obtains the `uploadUrl`, it must partition the binary file into sequential byte segments. Calculating chunk geometry correctly is where most custom implementations encounter unexpected failures.

### The 320 KiB Alignment Requirement

Microsoft Graph enforces a strict chunking constraint: upload chunk sizes must be multiples of 320 KiB or 327,680 bytes to avoid commit errors. The only exception to this rule is the final chunk of the file, which carries the remaining bytes regardless of whether its size divides evenly by `327,680`.

A single `320 KiB` fragment represents `327,680 bytes`. Common chunk multiples include:
* `10 multiples (3.125 MiB):` `3,276,800 bytes`
* `16 multiples (5.0 MiB):` `5,242,880 bytes`
* `32 multiples (10.0 MiB):` `10,485,760 bytes`
* `64 multiples (20.0 MiB):` `20,971,520 bytes`
* `192 multiples (60.0 MiB):` `62,914,560 bytes`

While Microsoft Graph allows chunk sizes up to `60 MiB`, selecting an optimal chunk size involves balancing network throughput against retry overhead. On stable cloud infrastructure, a `10 MiB` or `20 MiB` fragment size minimizes HTTP round trips. On consumer broadband or mobile uplinks, smaller fragments such as `5 MiB` isolate network interruptions to smaller byte ranges, preventing excessive retransmission.

### Required HTTP Headers for Fragment Uploads

When transmitting a fragment to the `uploadUrl`, clients issue an HTTP `PUT` request with specific headers:

* `Content-Length`: The exact size of the current chunk in bytes.
* `Content-Range`: The byte range formatted as `bytes {start}-{end}/{total_file_size}`. Both `start` and `end` are zero-indexed, inclusive offsets. For example, the first chunk of a file uses `bytes 0-10485759/100000000` when transmitting ten megabytes.

**Important Header Rule:** Omit the `Authorization` header when sending chunk `PUT` requests to the `uploadUrl`. Because the `uploadUrl` is already signed and pre-authenticated, including your Azure AD or Entra ID `Bearer` token can cause authentication rejections or signature verification conflicts on the storage endpoint.

### Node.js Implementation for Chunked Uploads

The following Node.js script demonstrates session initialization, byte slicing, header formatting, and sequential transmission using standard runtime APIs:

```javascript
import fs from "fs";
import path from "path";

async function uploadLargeFileToOneDrive(accessToken, driveId, parentFolderId, localFilePath) {
  const stats = fs.statSync(localFilePath);
  const fileSize = stats.size;
  const fileName = path.basename(localFilePath);
  const sessionEndpoint = `https://graph.microsoft.com/v1.0/drives/${driveId}/items/${parentFolderId}:/${fileName}:/createUploadSession`;
  const sessionResponse = await fetch(sessionEndpoint, {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${accessToken}`,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      item: {
        "@microsoft.graph.conflictBehavior": "rename",
        name: fileName
      }
    })
  });
  if (!sessionResponse.ok) {
    throw new Error(`Failed to create upload session: ${sessionResponse.statusText}`);
  }
  const { uploadUrl } = await sessionResponse.json();
  const chunkSize = 327680 * 32; // 10,485,760 bytes (32 multiples of 320 KiB)
  const fileDescriptor = fs.openSync(localFilePath, "r");
  const buffer = Buffer.alloc(chunkSize);
  let startByte = 0;
  try {
    while (startByte < fileSize) {
      const bytesRead = fs.readSync(fileDescriptor, buffer, 0, chunkSize, startByte);
      const endByte = startByte + bytesRead - 1;
      const chunkData = buffer.subarray(0, bytesRead);
      const chunkResponse = await fetch(uploadUrl, {
        method: "PUT",
        headers: {
          "Content-Length": String(bytesRead),
          "Content-Range": `bytes ${startByte}-${endByte}/${fileSize}`
        },
        body: chunkData
      });
      if (chunkResponse.status === 202) {
        startByte = endByte + 1;
      } else if (chunkResponse.status === 200 || chunkResponse.status === 201) {
        return await chunkResponse.json();
      } else {
        throw new Error(`Chunk upload failed: ${chunkResponse.status} ${chunkResponse.statusText}`);
      }
    }
  } finally {
    fs.closeSync(fileDescriptor);
  }
}
```

Each chunk upload returns `202 Accepted` containing a `nextExpectedRanges` array, confirming which byte ranges the server has persisted to disk.

## How to Handle Network Interruptions, Polling, and Commit Recovery

Network connections over the public internet encounter transient packet drops, TCP resets, and router reboots. The primary architectural benefit of Microsoft Graph upload sessions is the ability to recover gracefully without restarting the upload from the beginning.

### Querying Session Status to Resume Transfers

If an HTTP connection drops during chunk transmission, your client should not start over or create a new session. Instead, query the existing session status by issuing an empty HTTP `GET` request directly to the `uploadUrl`:

```http
GET https://sn3302.up.1drv.com/up/fe6143a4933a7e/.../upload_session_token
```

Like the chunk upload requests, this status query does not require an `Authorization` header. The server responds with a `200 OK` status containing the current upload state:

```json
{
  "expirationDateTime": "2026-10-12T14:30:00.000Z",
  "nextExpectedRanges": [
    "20971520-104857599"
  ]
}
```

The `nextExpectedRanges` array lists the byte positions that the server is currently waiting to receive. The client parses the first number in the range (in this case, `20971520`), seeks to that exact byte offset in the source file, and resumes uploading subsequent chunks.

### Common Error Codes and Recovery Strategies

When implementing production upload clients, prepare for specific HTTP status codes:

* **`404 Not Found`:** Indicates that the upload session has expired or was already committed. When a `404` occurs mid-transfer, recovery is impossible; your application must create a fresh upload session and transmit the file from byte zero.
* **`409 Conflict`:** Occurs if another process modified or created a file with the same name during the upload window, and conflict behavior was set to `fail`.
* **`429 Too Many Requests`:** Microsoft Graph enforces dynamic request rate limits. When your client receives a `429`, inspect the `Retry-After` response header, pause execution for the designated number of seconds, and retry the request using exponential backoff with random jitter.
* **`500`, `502`, `503`, `504` Gateway Errors:** Transient server or infrastructure faults. Query the session status to confirm which byte ranges were successfully committed before retrying the failed chunk.

### Cancelling and Deleting Upload Sessions

If a user cancels an upload, or if an ingestion worker encounters an unrecoverable local error, release the server-side storage allocation by deleting the session:

```http
DELETE https://sn3302.up.1drv.com/up/fe6143a4933a7e/.../upload_session_token
```

Microsoft Graph deletes the temporary staging file and returns `204 No Content`. Proactively deleting abandoned sessions prevents quota consumption and frees staging storage in your tenant.

## Connecting Microsoft Storage to Fast.io Workspaces for AI Agents

Many technical teams and modern organizations maintain terabytes of enterprise data across Microsoft OneDrive and SharePoint. However, as autonomous agents, coding assistants, and automated analysis pipelines become standard operational tools, interacting with massive files through native Microsoft Graph APIs introduces significant architectural friction.

### Challenges of Direct Agent Ingestion

When an autonomous agent needs to inspect, summarize, or extract data from large enterprise files, downloading hundreds of megabytes of raw binaries through Microsoft Graph creates three immediate bottlenecks:

1. **High Latency and Bandwidth Consumption:** Slicing and streaming large files over HTTP consumes considerable memory and network bandwidth in containerized agent environments.
2. **Context Window Saturation:** Feeding massive raw documents directly into LLM prompts quickly exhausts context limits and inflates inference costs.
3. **Connector Rate Limits:** Repeated API calls across multiple agents frequently trip Microsoft Graph throttling quotas (`429 Too Many Requests`), stalling agent workflows.

In Claude Cowork, OneDrive operates through a native connector, while SharePoint was not measured in that benchmark. To coordinate file access for agentic teams, Fast.io provides a purpose-built workspace substrate that coordinates persistent storage with autonomous AI workflows.

### The Fast.io Cloud Sync and Workspace Architecture

Rather than replacing your established enterprise storage, Fast.io works alongside your existing infrastructure. Teams keep their primary files in OneDrive or SharePoint, while Fast.io Cloud Sync mirrors designated folders into a shared Fast.io workspace.

* **Flexible Synchronization:** Fast.io Cloud Sync supports one-way or two-way synchronization on a schedule or on demand. SharePoint document libraries connect directly through the OneDrive connector. (synchronization is never continuous, live, or real-time).
* **Measured Performance:** The connector comparison is published at [https://fast.io/benchmarks/](https://fast.io/benchmarks/) and that page is the only place its numbers live. Fastio was measured the fastest and the lowest cost of the providers tested.
* **Intelligence Mode and RAG:** When files land in a Fast.io workspace, Intelligence Mode auto-indexes content for hybrid search (full-text keyword matching plus semantic vector search). Agents query specific concepts and retrieve precise citations without needing to ingest full multi-gigabyte binaries.
* **Structured Data Extraction:** With Metadata Views, teams can convert complex documents into typed, queryable tabular schemas without building custom parsing scripts or OCR pipelines. Explore this capability further on the [Fast.io Document Data Extraction](/product/document-data-extraction/) page.
* **Remote MCP Integration:** Autonomous agents connect to Fast.io through a remote Model Context Protocol server over Streamable HTTP. Clients use `https://mcp.fast.io/mcp/tools` for Claude apps and general agents, or `https://mcp.fast.io/mcp/code` for coding agents. Detailed configuration steps are available in the [Fast.io MCP documentation](https://mcp.fast.io/docs).

For teams managing collaborative assets and shared repositories, exploring [Fast.io Workspaces](/product/workspaces/) and dedicated [AI Storage](/product/ai-storage/) provides a persistent, auditable foundation where human team members and AI agents collaborate effectively. To see how Fast.io compares with traditional cloud storage, review the [OneDrive alternative comparison](/alternatives/onedrive/).

## Frequently asked questions

### How do I upload a large file using Microsoft Graph API?

Upload large files by sending a POST request to the createUploadSession endpoint for your target drive item. Microsoft Graph returns an uploadUrl where your application sends sequential PUT requests containing file chunks. Each chunk must specify its byte range using Content-Range and Content-Length headers, and the final chunk returns the committed item metadata.

### What is the maximum file size for Microsoft Graph upload sessions?

Microsoft Graph upload sessions support file transfers up to `250 GB` for individual files in OneDrive and SharePoint document libraries. In contrast, Microsoft Graph simple PUT calls cap out at 250 MB and cannot resume if the network connection drops.

### How does Microsoft Graph chunk alignment work?

Every chunk uploaded to a Microsoft Graph upload session must have a byte size that is an exact multiple of 320 KiB or 327,680 bytes. Recommended chunk sizes range between `5 MiB` and `10 MiB`, up to a maximum chunk size of `60 MiB`. The only exception to the `320 KiB` rule is the final fragment, which carries whatever remaining bytes are needed to complete the file.

### Why must the Authorization header be omitted when uploading chunks to the uploadUrl?

The uploadUrl returned by createUploadSession is an opaque, pre-authenticated endpoint that already contains the required authorization tokens and cryptographic signatures in its query parameters. Passing an Authorization Bearer header during chunk PUT requests can cause signature mismatches or authentication errors on Microsoft storage nodes.

### How does session recovery work when a chunk upload fails mid-transfer?

When a network interruption occurs, send an empty GET request to the uploadUrl without creating a new session. The server responds with `200 OK` and a nextExpectedRanges array indicating which byte offsets are missing. Your client seeks to that byte position and resumes chunk uploads without restarting from zero.

## Sources

- [Microsoft Learn: Upload small files - Microsoft Graph](https://learn.microsoft.com/en-us/graph/api/driveitem-put-content?view=graph-rest-1.0): Microsoft Graph simple PUT calls cap out at 250 MB
- [Microsoft Learn: Upload large files with an upload session](https://learn.microsoft.com/en-us/graph/api/driveitem-createuploadsession?view=graph-rest-1.0): Upload chunk sizes must be multiples of 320 KiB or 327,680 bytes

## About Fast.io

Fast.io provides shared workspaces where people and AI agents work on the same files, with built-in semantic search and citation-backed chat over what they hold. Agents reach it through a remote MCP server, a REST API at https://api.fast.io/current/, and a command line client published on npm as @vividengine/fastio-cli. MCP setup is at https://mcp.fast.io/docs: Claude and most MCP clients connect to https://mcp.fast.io/mcp/tools, ChatGPT to https://mcp.fast.io/mcp/operations, and coding agents to https://mcp.fast.io/mcp/code.
