Chilkat2-Python
Chilkat2-Python
OneDrive -- Upload Large Files with an Upload Session
See more OneDrive Examples
Demonstrates how to upload large files with an upload session. See OneDrive Upload Session for more general information.Chilkat Chilkat2-Python Downloads
import sys
import chilkat2
success = False
# This example requires the Chilkat API to have been previously unlocked.
# See Global Unlock Sample for sample code.
# This example uses the OAuth client credentials flow.
# See How to Create an Azure App Registration for OAuth 2.0 Client Credentials
# Use your client ID, client secret, and tenant ID in the following lines
json = chilkat2.JsonObject()
json.UpdateString("client_id","2871da2c-8176-4b7f-869b-2311aa82e743")
json.UpdateString("client_secret","2hu9Q~r5QuryUcEkNbg1btLtnfU1VUXzhSCG6brH")
json.UpdateString("scope","https://graph.microsoft.com/.default")
json.UpdateString("token_endpoint","https://login.microsoftonline.com/114d7ed6-71bf-4dbe-a866-748364121bf2/oauth2/v2.0/token")
http = chilkat2.Http()
http.AuthToken = json.Emit()
# ----------------------------------------------------------------------------
# Step 1: Create an upload session
# To begin a large file upload, your app must first request a new upload session. This creates a
# temporary storage location where the bytes of the file will be saved until the complete file is uploaded.
# Once the last byte of the file has been uploaded the upload session is completed and the final file is shown
# in the destination folder.
# Send the following POST to create an upload session:
# If not using "me", then the path should be /v1.0/users/{id | userPrincipalName}/...
# POST /v1.0/users/{user_id}/drive/root:/{path_to_item}:/createUploadSession
http.SetUrlVar("path_to_item","/somefolder/big.zip")
http.SetUrlVar("user_id","4fe732c3-322e-4a6b-b729-2fd1eb5c6104")
url = "https://graph.microsoft.com/v1.0/users/{$user_id}/drive/root:/{$path_to_item}:/createUploadSession"
resp = chilkat2.HttpResponse()
success = http.HttpStr("POST",url,"{}","utf-8","application/json",resp)
if (success == False):
print(http.LastErrorText)
sys.exit()
# If successful, a 200 status code is returned, with the session details (in JSON format).
jsonSession = chilkat2.JsonObject()
jsonSession.EmitCompact = False
jsonSession.Load(resp.BodyStr)
if (resp.StatusCode != 200):
print(jsonSession.Emit())
print("Response status = " + str(resp.StatusCode))
sys.exit()
print(jsonSession.Emit())
# A sample response:
# {
# "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#microsoft.graph.uploadSession",
# "uploadUrl": "https://api.onedrive.com/rup/3a33fceb9b74cc15/eyJSZXNvdXJjZUlEI ... 65yDYUiS3JTDnnhqCHxw",
# "expirationDateTime": "2017-06-11T12:40:23.239Z",
# "nextExpectedRanges": [
# "0-"
# ]
# }
#
# ----------------------------------------------------------------------------
# Step 2: Upload Data in Segments (a.k.a. Fragments or Chunks)
# Microsoft states this requirement: Use a fragment size that is a multiple of 320 KiB (320 * 1024 bytes).
# Failing to use a fragment size that is a multiple of 320 KiB can result in large file transfers failing after the
# last fragment is uploaded. (Note: This is a detail imposed by Microsoft's OneDrive server-side implementation.)
fragSize = 320 * 1024
localFilePath = "qa_data/zips/big.zip"
# Upload the file big.zip in 320KiB segments.
# Note: The FileSize method returns a signed 32-bit integer. If the file is potentially larger than 2GB, call FileSizeStr instead to return
# the size of the file as a string, then convert to an integer value.
fac = chilkat2.FileAccess()
fileSize = fac.FileSize(localFilePath)
# Open the file to get the number of fragments.
success = fac.OpenForRead(localFilePath)
if (success == False):
print(fac.LastErrorText)
sys.exit()
numFragments = fac.GetNumBlocks(fragSize)
fac.FileClose()
i = 0
print("fileSize = " + str(fileSize))
print("numFragments = " + str(numFragments))
uploadUrl = chilkat2.Url()
uploadUrl.ParseUrl(jsonSession.StringOf("uploadUrl"))
json.EmitCompact = False
req = chilkat2.HttpRequest()
req.HttpVerb = "PUT"
req.Path = uploadUrl.PathWithQueryParams
req.ContentType = "application/octet-stream"
sbOffset = chilkat2.StringBuilder()
sbNumBytes = chilkat2.StringBuilder()
sbRange = chilkat2.StringBuilder()
# IMPORTANT: The uploadUrl is a temporary URL to be used to upload the fragment.
# It requires no authentication (because the URL itself could only have been obtained from an authenticated
# request to start the upload session). Therefore, do not allow the upload URL to be publicly seen,
# otherwise anybody could upload to your OneDrive.
http.AuthToken = ""
bytesRemaining = fileSize
while i < numFragments :
# The success response code for intermediate chunks is 202,
# whereas the final chunk will have a 201 success response where
# the response body is the JSON DriveItem.
chunkSize = fragSize
expectedStatusCode = 202
if (bytesRemaining < chunkSize):
chunkSize = bytesRemaining
expectedStatusCode = 201
print(" this chunkSize = " + str(chunkSize))
# Indicate the fragment in the local file to be streamed in the upload.
sbOffset.Clear()
sbOffset.AppendInt(i * fragSize)
sbNumBytes.Clear()
sbNumBytes.AppendInt(chunkSize)
req.StreamChunkFromFile(localFilePath,sbOffset.GetAsString(),sbNumBytes.GetAsString())
# The Content-Range header field must be set for this fragment. For example:
# Content-Range: bytes 0-25/128
sbRange.SetString("bytes start-end/fileSize")
numReplaced = sbRange.ReplaceI("start",i * fragSize)
numReplaced = sbRange.ReplaceI("end",i * fragSize + chunkSize - 1)
numReplaced = sbRange.ReplaceI("fileSize",fileSize)
req.AddHeader("Content-Range",sbRange.GetAsString())
print(" this content-range: " + sbRange.GetAsString())
domain = uploadUrl.Host
success = http.HttpSReq(domain,443,True,req,resp)
if (success == False):
print(http.LastErrorText)
sys.exit()
json.Load(resp.BodyStr)
# A 202 response status code indicates success.
if (resp.StatusCode != expectedStatusCode):
print(json.Emit())
print("Response status = " + str(resp.StatusCode))
sys.exit()
print(json.Emit())
print("---- Chunk " + str(i) + " uploaded ----")
bytesRemaining = bytesRemaining - chunkSize
i = i + 1
print("data uploaded.")
# ----------------------------------------------------------------------------
# Sample output for the above session:
# {
# "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#microsoft.graph.uploadSession",
# "uploadUrl": "https://api.onedrive.com/rup/3a33fceb9b74cc15/eyJSZXNvd ... QoKK2iuh1A",
# "expirationDateTime": "2017-06-11T14:04:45.438Z",
# "nextExpectedRanges": [
# "0-"
# ]
# }
#
# fileSize = 1366807
# numFragments = 5
# this chunkSize = 327680
# this content-range: bytes 0-327679/1366807
# {
# "expirationDateTime": "2017-06-11T14:04:45.438Z",
# "nextExpectedRanges": [
# "327680-1366806"
# ]
# }
#
# ---- Chunk 0 uploaded ----
# this chunkSize = 327680
# this content-range: bytes 327680-655359/1366807
# {
# "expirationDateTime": "2017-06-11T14:04:45.438Z",
# "nextExpectedRanges": [
# "655360-1366806"
# ]
# }
#
# ---- Chunk 1 uploaded ----
# this chunkSize = 327680
# this content-range: bytes 655360-983039/1366807
# {
# "expirationDateTime": "2017-06-11T14:04:45.438Z",
# "nextExpectedRanges": [
# "983040-1366806"
# ]
# }
#
# ---- Chunk 2 uploaded ----
# this chunkSize = 327680
# this content-range: bytes 983040-1310719/1366807
# {
# "expirationDateTime": "2017-06-11T14:04:45.438Z",
# "nextExpectedRanges": [
# "1310720-1366806"
# ]
# }
#
# ---- Chunk 3 uploaded ----
# this chunkSize = 56087
# this content-range: bytes 1310720-1366806/1366807
# {
# "createdBy": {
# "application": {
# "displayName": "Chilkat",
# "id": "441c9990"
# },
# "user": {
# "id": "3a33fceb9b74cc15"
# }
# },
# "createdDateTime": "2017-06-04T14:04:47.247Z",
# "cTag": "aYzozQTMzRkNFQjlCNzRDQzE1ITQ4NjguMjU3",
# "eTag": "aM0EzM0ZDRUI5Qjc0Q0MxNSE0ODY4LjA",
# "id": "3A33FCEB9B74CC15!4868",
# "lastModifiedBy": {
# "application": {
# "displayName": "Chilkat",
# "id": "441c9990"
# },
# "user": {
# "id": "3a33fceb9b74cc15"
# }
# },
# "lastModifiedDateTime": "2017-06-04T14:04:47.247Z",
# "name": "big.zip",
# "parentReference": {
# "driveId": "3a33fceb9b74cc15",
# "id": "3A33FCEB9B74CC15!4862",
# "name": "someFolder",
# "path": "/drive/root:/someFolder"
# },
# "size": 1366807,
# "webUrl": "https://1drv.ms/u/s!ABXMdJvr_DM6pgQ",
# "file": {
# "hashes": {
# "sha1Hash": "252059AA13004220DB912B97D4D3FF9599CCD8D9"
# },
# "mimeType": "application/zip"
# },
# "fileSystemInfo": {
# "createdDateTime": "2017-06-04T14:04:47.246Z",
# "lastModifiedDateTime": "2017-06-04T14:04:47.246Z"
# },
# "tags": [
# ],
# "lenses": [
# ]
# }
#
# Response status = 201