This post is a contribution from Adam Burns, an engineer with the SharePoint Developer Support team
A while back, I wrote an article explaining that you must use File Chunking if you want to upload files larger than 250 MB to SharePoint or OneDrive for Business, using either the SharePoint REST API or CSOM. This is because the file upload limit is set in the service and cannot be changed. Using the Microsoft Graph API is even more restrictive. The file size limit for uploading files is so small (4 MB) that you really should always use the chunking method, but the implementation is a little different than it is with the SharePoint REST API. Also, to get an access token for Graph you will always need to use an Azure AD authorization endpoint.
The main operation you need is /createUploadSession. The details of the API are clearly documented here: https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_createuploadsession#create-an-upload-session
You’ll need to write more code than you may expect, to do this correctly.
Here are the main steps you need to perform to upload a file using the /createUploadSession approach:
- Use /createUploadSession to retrieve an upload URL which contains the session identifier. The response will look like this:
- Use PUT to upload chunks to the uploadUrl. Each chunk should start with a starting range represented by the first number in the “nextExpectedRanges” value in the JSON response from the last PUT. As shown above, the first range will always start with zero. Don’t rely on the end of the range in the “nextExpectedRanges” value. For one thing, this is an array and you may occasionally see multiple ranges. You will usually just pick the starting number of the 0th member of the array. As noted in the documentation, you should use a chunk size which is divisible by 320 KiB (327,680 bytes). So, the headers of your PUT request will look like this:
Both the linked examples below use 4 main functions to do all this work:
- getUploadSession() which makes the initial POST request that retrieves the uploadUrl
- uploadChunks() which has the logic to loop based on the response to each PUT call. It in turn calls:
- readFragmentAsync() which actually slices up the byte array using FileReader and it’s onloadend event. Here is and example of that method:
- uploadChunk(). This method is also called by uploadChunks to actually execute the ajax PUT call.
All this results in some pretty lengthy code. My examples may be more verbose because I put in a lot of logging to illustrate the process. You may figure out a way to make the code more efficient and terse, but for a production scenario, you will have to add additional code to handle unexpected situations. These scenarios are explained at: https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_createuploadsession#create-an-upload-session. My purpose with this blog post was to expose some real-world code examples, because, at the time of this writing, there is almost nothing out there for this API. Once the basic approach is understood, it should not be hard to create tests and guard code to handle unexpected conditions.
I want to point out two things which are not mentioned in the above-referenced article.
- The articles and examples show the following request body for the initial call to create the upload session:
As you would expect, conflictBehavior is an enum that would provide different behaviors on the server side when there is a name conflict for the uploaded file. The definition of the enum, describes the following three values: Fail, Replace, Rename.
When you use “rename,” as the conflict behavior, the file gets an incremented integer as a string appended to the file name, so for “myFile.docx” you would get a new file uploaded called “myFile 1.docx.”
When you use “replace,” you end up replacing the file and all the metadata is updated. When you use “fail,” as the conflict behavior, the initial POST receives a HTTP 409 response ("The specified item name already exists.") and your code will have to handle the exception.
- In most cases, when you upload the final chunk of the file, you will receive a response with the HTTP status code of 201. If you specify a conflict behavior of “replace,” you will receive a HTTP 200 response instead. Therefore, you must handle the response with code with something like: