├── .gitattributes ├── .gitignore ├── Azure_app_signup_step_by_step.md ├── OneDrive_Gaph_tutorial.ipynb ├── README.md └── assets ├── 01.PNG ├── 02.PNG ├── 03.PNG ├── 04.PNG ├── 05.PNG ├── 06.PNG ├── 07.PNG ├── 08.PNG ├── 09.PNG └── 10.PNG /.gitattributes: -------------------------------------------------------------------------------- 1 | *.ipynb linguist-language=Python 2 | 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /**/.ipynb_checkpoints 3 | /**/__pycache__ 4 | /venv 5 | -------------------------------------------------------------------------------- /Azure_app_signup_step_by_step.md: -------------------------------------------------------------------------------- 1 | ```python 2 | # Program: Accessing OneDrive via Graph API 3 | # Author: Pranab Das (GitHub: @pranabdas) 4 | # Version: 20191104 5 | ``` 6 | 7 | # Azure App Signup step by step 8 | 9 | 1. Go to https://portal.azure.com 10 | 11 | ![01.PNG](/assets/01.PNG) 12 | 13 | 2. Navigate to Azure Active Directory 14 | 15 | ![02.PNG](/assets/02.PNG) 16 | 17 | 18 | 3. Select App Registration 19 | 20 | ![03.PNG](/assets/03.PNG) 21 | 22 | 4. Click New Registration 23 | 24 | ![04.PNG](/assets/04.PNG) 25 | 26 | 5. Give a name to your app, set the redirect URL, and hit Registration button. 27 | 28 | ![05.PNG](/assets/05.PNG) 29 | 30 | 6. Note down the client ID and go to API permissions. 31 | 32 | ![06.PNG](/assets/06.PNG) 33 | 34 | 7. Click Add permissions, select Microsoft Graph. 35 | 36 | ![07.PNG](/assets/07.PNG) 37 | 38 | 8. Choose Delegated permission. 39 | 40 | ![08.PNG](/assets/08.PNG) 41 | 42 | 9. We will add Files.ReadWrite.All for our purpose. 43 | 44 | ![09.PNG](/assets/09.PNG) 45 | 46 | 10. Now go to Authentication tab, and enable Access token. Click the save button, and now we are all set to go. 47 | 48 | ![10.PNG](/assets/10.PNG) 49 | -------------------------------------------------------------------------------- /OneDrive_Gaph_tutorial.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "# Program: Accessing OneDrive via Graph API\n", 10 | "# Author: Pranab Das (GitHub: @pranabdas)\n", 11 | "# Version: 20210820" 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": 2, 17 | "metadata": {}, 18 | "outputs": [], 19 | "source": [ 20 | "# requirements\n", 21 | "import requests\n", 22 | "import json\n", 23 | "import urllib\n", 24 | "import os\n", 25 | "from getpass import getpass\n", 26 | "import time\n", 27 | "from datetime import datetime" 28 | ] 29 | }, 30 | { 31 | "cell_type": "markdown", 32 | "metadata": {}, 33 | "source": [ 34 | "## Get Access token\n", 35 | "\n", 36 | "### Token flow authentication" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": 3, 42 | "metadata": {}, 43 | "outputs": [ 44 | { 45 | "name": "stdout", 46 | "output_type": "stream", 47 | "text": [ 48 | "Click over this link https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=362422eb-d9d6-4245-9eca-2be5cf256450&scope=files.readwrite&response_type=token&redirect_uri=http%3A//localhost%3A8080/\n", 49 | "Sign in to your account, copy the whole redirected URL.\n", 50 | "Paste the URL here :http://localhost:8080/#access_token=EwBYA8l6BAAUO9chh8cJscQLmU%2bLSWpbnr0vmwwAAXbgH8Q919pMC8ErHXfcrM/uuPvmmsIyKar8nmAp1mvv/0QwrjAkSBM8Y6sJqpPEPrGKBrDHairoIVrQK7FhGCtYLGEy3P88wnaKGr4NYygckbi2g6P4S5KPt7d3m3/7XuAhLips6jwD3X8g89a72SajQaa1xbPFw2TfUed/UG6kqUxzlVUy4gkPCBMm%2bizQ3mP7lXRbmeXqCY5omTSQz6djvkCcjXf9TqC1WfVpRLHGc7yLUPcg15nGmdMfwRxWDxYi8rlD34Y0cVYt4KYw3B2VkdxyMvCWqARgauWApLYTFopGZIUQ8M0Fggb89PncdhHInKehD8Rp7rkBJIhkfIIDZgAACBnA%2btK5eKnhKAJmVnI6%2b2MwF54q9NR04O9xTn0Py/uOJPpyGeAtMRBgHTSI6Eh/Bwr/ybQh2TMbfNBbqpOEjPYx0KDhDhrcS1LldJKKoYj2EOREEkwKZNKYfmTdO1jWQ/MohoOFawGB29gdSyJxkqgRHrC2RedL3wFYMOxE78ehVvfCl1/UqBR4Z4ypPMZ%2bsFlyCOCQ6E2fiLyJt0AF5wZencLGoAhXdlh/gIDVZuSZBVQXZuEP19d07IGqLmwDoVnhecniQMjy3cLVQ5v0vlT15b/GpuESNhtgrdQwGT307F9gHPVO6U9UMzfT1iEx%2bjqOBR5paJz8OiIZOG3SZmqZFB4c606Vycio3BVnkXyNlf6kBZfJMNVLB4IubmXSbM%2byFjadP1Cq3pc2dsQRx%2bMqhYCDYS%2bYm4yBqHW0r/XfLrs/QmiIgVtAneHyw99TYVFEO2sqM3MLPZS1W8Wm0cFvwvfxuDI4cDllhjkX5jPy0wSD35c9rDZ8gwWdpR1x6Xc/XaTsn1eQEb9CcsZxyyIeJ6SA9t2kysZ1udqbu4xqIuMt3QtIdYA3tDDIg9IPJtF7tuC48G5tjm7BlfOANxhfsg8USYtjovd3KC4Jl4w87OBeiGrRQgaoI4pEfZVgYPa4TuOYe6ZuYCEyNW8GYumvetzmkRkrMBwicAqJ5KXVco5Lird6gCbQSWFjBTfxtdzXFKCiEgcQSDAm88xTwN2LvBKsrbV17QkEyNYqcVzo1CdsAg%3d%3d&token_type=bearer&expires_in=3600&scope=Files.ReadWrite%20Files.ReadWrite.All\n", 51 | "Connected to the OneDrive of ( personal ). \n", 52 | "Connection valid for one hour. Reauthenticate if required.\n" 53 | ] 54 | } 55 | ], 56 | "source": [ 57 | "URL = 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize'\n", 58 | "client_id = \"362422eb-d9d6-4245-9eca-2be5cf256450\" \n", 59 | "permissions = ['files.readwrite']\n", 60 | "response_type = 'token'\n", 61 | "redirect_uri = 'http://localhost:8080/' \n", 62 | "scope = ''\n", 63 | "for items in range(len(permissions)):\n", 64 | " scope = scope + permissions[items]\n", 65 | " if items < len(permissions)-1:\n", 66 | " scope = scope + '+'\n", 67 | " \n", 68 | "print('Click over this link ' +URL + '?client_id=' + client_id + '&scope=' + scope + '&response_type=' + response_type+\\\n", 69 | " '&redirect_uri=' + urllib.parse.quote(redirect_uri))\n", 70 | "print('Sign in to your account, copy the whole redirected URL.')\n", 71 | "code = input(\"Paste the URL here :\")\n", 72 | "token = code[(code.find('access_token') + len('access_token') + 1) : (code.find('&token_type'))]\n", 73 | "URL = 'https://graph.microsoft.com/v1.0/' \n", 74 | "HEADERS = {'Authorization': 'Bearer ' + token}\n", 75 | "response = requests.get(URL + 'me/drive/', headers = HEADERS)\n", 76 | "if (response.status_code == 200):\n", 77 | " response = json.loads(response.text)\n", 78 | " print('Connected to the OneDrive of', response['owner']['user']['displayName']+' (',response['driveType']+' ).', \\\n", 79 | " '\\nConnection valid for one hour. Reauthenticate if required.')\n", 80 | "elif (response.status_code == 401):\n", 81 | " response = json.loads(response.text)\n", 82 | " print('API Error! : ', response['error']['code'],\\\n", 83 | " '\\nSee response for more details.')\n", 84 | "else: \n", 85 | " response = json.loads(response.text)\n", 86 | " print('Unknown error! See response for more details.')" 87 | ] 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "metadata": {}, 92 | "source": [ 93 | "Looks all right. We have got the access token, and included in the HEADERS. You can print response to see more. Go ahead with OneDrive operations." 94 | ] 95 | }, 96 | { 97 | "cell_type": "markdown", 98 | "metadata": {}, 99 | "source": [ 100 | "### Code flow authentication\n", 101 | "\n", 102 | "Code flow returns both `access_token` and `refresh_token` which can be used to\n", 103 | "request new `access_token` and `refresh_token` for persistent session. If you \n", 104 | "are using organization account, you might require consent of organization administrator. \n" 105 | ] 106 | }, 107 | { 108 | "cell_type": "code", 109 | "execution_count": null, 110 | "metadata": {}, 111 | "outputs": [], 112 | "source": [ 113 | "# Get code\n", 114 | "URL = 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize'\n", 115 | "client_id = \"362422eb-d9d6-4245-9eca-2be5cf256450\"\n", 116 | "permissions = ['offline_access', 'files.readwrite', 'User.Read']\n", 117 | "response_type = 'code'\n", 118 | "redirect_uri = 'http://localhost:8080/'\n", 119 | "scope = ''\n", 120 | "for items in range(len(permissions)):\n", 121 | " scope = scope + permissions[items]\n", 122 | " if items < len(permissions)-1:\n", 123 | " scope = scope + '+'\n", 124 | "\n", 125 | "print('Click over this link ' +URL + '?client_id=' + client_id + '&scope=' + scope + '&response_type=' + response_type+\\\n", 126 | " '&redirect_uri=' + urllib.parse.quote(redirect_uri))\n", 127 | "print('Sign in to your account, copy the whole redirected URL.')\n", 128 | "code = getpass(\"Paste the URL here :\")\n", 129 | "code = code[(code.find('?code') + len('?code') + 1) :]\n", 130 | "\n", 131 | "URL = 'https://login.microsoftonline.com/common/oauth2/v2.0/token'\n", 132 | "\n", 133 | "response = requests.post(URL + '?client_id=' + client_id + '&scope=' + scope + '&grant_type=authorization_code' +\\\n", 134 | " '&redirect_uri=' + urllib.parse.quote(redirect_uri)+ '&code=' + code)" 135 | ] 136 | }, 137 | { 138 | "cell_type": "code", 139 | "execution_count": null, 140 | "metadata": {}, 141 | "outputs": [], 142 | "source": [ 143 | "# Get token\n", 144 | "data = {\n", 145 | " \"client_id\": client_id,\n", 146 | " \"scope\": permissions,\n", 147 | " \"code\": code,\n", 148 | " \"redirect_uri\": redirect_uri,\n", 149 | " \"grant_type\": 'authorization_code',\n", 150 | " \"client_secret\": client_secret\n", 151 | "}\n", 152 | "\n", 153 | "response = requests.post(URL, data=data)\n", 154 | "\n", 155 | "token = json.loads(response.text)[\"access_token\"]\n", 156 | "refresh_token = json.loads(response.text)[\"refresh_token\"]" 157 | ] 158 | }, 159 | { 160 | "cell_type": "code", 161 | "execution_count": null, 162 | "metadata": {}, 163 | "outputs": [], 164 | "source": [ 165 | "# Refresh token\n", 166 | "def get_refresh_token():\n", 167 | " data = {\n", 168 | " \"client_id\": client_id,\n", 169 | " \"scope\": permissions,\n", 170 | " \"refresh_token\": refresh_token,\n", 171 | " \"redirect_uri\": redirect_uri,\n", 172 | " \"grant_type\": 'refresh_token',\n", 173 | " \"client_secret\": 'xxxx-yyyy-zzzz',\n", 174 | " }\n", 175 | "\n", 176 | " response = requests.post(URL, data=data)\n", 177 | "\n", 178 | " token = json.loads(response.text)[\"access_token\"]\n", 179 | " refresh_token = json.loads(response.text)[\"refresh_token\"]\n", 180 | " last_updated = time.mktime(datetime.today().timetuple())\n", 181 | "\n", 182 | " return token, refresh_token, last_updated" 183 | ] 184 | }, 185 | { 186 | "cell_type": "code", 187 | "execution_count": null, 188 | "metadata": {}, 189 | "outputs": [], 190 | "source": [ 191 | "token, refresh_token, last_updated = get_refresh_token()" 192 | ] 193 | }, 194 | { 195 | "cell_type": "markdown", 196 | "metadata": {}, 197 | "source": [ 198 | "If you have a large data to upload, you may use below mock code inside your upload loop:\n", 199 | "\n", 200 | "```python\n", 201 | "elapsed_time = time.mktime(datetime.today().timetuple()) - last_updated\n", 202 | "\n", 203 | "if (elapsed_time < 45*60*60):\n", 204 | " do_something()\n", 205 | "else if (elapsed_time < 59*60*60):\n", 206 | " token, refresh_token, last_updated = get_refresh_token()\n", 207 | "else:\n", 208 | " go_to_code_flow()\n", 209 | "```" 210 | ] 211 | }, 212 | { 213 | "cell_type": "markdown", 214 | "metadata": {}, 215 | "source": [ 216 | "## OneDrive operations" 217 | ] 218 | }, 219 | { 220 | "cell_type": "code", 221 | "execution_count": null, 222 | "metadata": {}, 223 | "outputs": [], 224 | "source": [ 225 | "URL = 'https://graph.microsoft.com/v1.0/'\n", 226 | "\n", 227 | "HEADERS = {'Authorization': 'Bearer ' + token}\n", 228 | "\n", 229 | "response = requests.get(URL + 'me/drive/', headers = HEADERS)\n", 230 | "if (response.status_code == 200):\n", 231 | " response = json.loads(response.text)\n", 232 | " print('Connected to the OneDrive of', response['owner']['user']['displayName']+' (',response['driveType']+' ).', \\\n", 233 | " '\\nConnection valid for one hour. Refresh token if required.')\n", 234 | "elif (response.status_code == 401):\n", 235 | " response = json.loads(response.text)\n", 236 | " print('API Error! : ', response['error']['code'],\\\n", 237 | " '\\nSee response for more details.')\n", 238 | "else:\n", 239 | " response = json.loads(response.text)\n", 240 | " print('Unknown error! See response for more details.')" 241 | ] 242 | }, 243 | { 244 | "cell_type": "markdown", 245 | "metadata": {}, 246 | "source": [ 247 | "### List folders unde root\n", 248 | "\n", 249 | "We will pring both directory names and item-d" 250 | ] 251 | }, 252 | { 253 | "cell_type": "code", 254 | "execution_count": 4, 255 | "metadata": {}, 256 | "outputs": [ 257 | { 258 | "name": "stdout", 259 | "output_type": "stream", 260 | "text": [ 261 | "Documents | item-id > C1465DBECD7188C9!103\n", 262 | "Pictures | item-id > C1465DBECD7188C9!104\n", 263 | "Getting started with OneDrive.pdf | item-id > C1465DBECD7188C9!102\n" 264 | ] 265 | } 266 | ], 267 | "source": [ 268 | "items = json.loads(requests.get(URL + 'me/drive/root/children', headers=HEADERS).text)\n", 269 | "items = items['value']\n", 270 | "for entries in range(len(items)):\n", 271 | " print(items[entries]['name'], '| item-id >', items[entries]['id'])" 272 | ] 273 | }, 274 | { 275 | "cell_type": "markdown", 276 | "metadata": {}, 277 | "source": [ 278 | "### Create new folder (in the root directory)" 279 | ] 280 | }, 281 | { 282 | "cell_type": "code", 283 | "execution_count": 5, 284 | "metadata": {}, 285 | "outputs": [], 286 | "source": [ 287 | "url = URL + 'me/drive/root/children/'\n", 288 | "body = {\n", 289 | " \"name\": \"New_Folder\",\n", 290 | " \"folder\": {},\n", 291 | " \"@microsoft.graph.conflictBehavior\": \"rename\"\n", 292 | "}\n", 293 | "response = json.loads(requests.post(url, headers=HEADERS, json=body).text)" 294 | ] 295 | }, 296 | { 297 | "cell_type": "markdown", 298 | "metadata": {}, 299 | "source": [ 300 | "Now lets list the directory again" 301 | ] 302 | }, 303 | { 304 | "cell_type": "code", 305 | "execution_count": 6, 306 | "metadata": {}, 307 | "outputs": [ 308 | { 309 | "name": "stdout", 310 | "output_type": "stream", 311 | "text": [ 312 | "Documents | item-id > C1465DBECD7188C9!103\n", 313 | "New_Folder | item-id > C1465DBECD7188C9!106\n", 314 | "Pictures | item-id > C1465DBECD7188C9!104\n", 315 | "Getting started with OneDrive.pdf | item-id > C1465DBECD7188C9!102\n" 316 | ] 317 | } 318 | ], 319 | "source": [ 320 | "items = json.loads(requests.get(URL + 'me/drive/root/children', headers=HEADERS).text)\n", 321 | "items = items['value']\n", 322 | "for entries in range(len(items)):\n", 323 | " print(items[entries]['name'], '| item-id >', items[entries]['id'])" 324 | ] 325 | }, 326 | { 327 | "cell_type": "markdown", 328 | "metadata": {}, 329 | "source": [ 330 | "Here we go, we have successfully created the folder New_Folder." 331 | ] 332 | }, 333 | { 334 | "cell_type": "markdown", 335 | "metadata": {}, 336 | "source": [ 337 | "#### List folders under a sub-folder (need to use item-id)\n", 338 | "Note that if you need to create or list sub-folders, you need to use the item-id. The path/folder notation does not work everywhere. " 339 | ] 340 | }, 341 | { 342 | "cell_type": "code", 343 | "execution_count": 7, 344 | "metadata": {}, 345 | "outputs": [], 346 | "source": [ 347 | "url = URL + 'me/drive/items/C1465DBECD7188C9!106/children'\n", 348 | "items = json.loads(requests.get(url, headers=HEADERS).text)\n", 349 | "items = items['value']\n", 350 | "for entries in range(len(items)):\n", 351 | " print(items[entries]['name'], '| item-id >', items[entries]['id'])" 352 | ] 353 | }, 354 | { 355 | "cell_type": "markdown", 356 | "metadata": {}, 357 | "source": [ 358 | "Well there are no files or folders under the New_Folder. Ok let's create one. " 359 | ] 360 | }, 361 | { 362 | "cell_type": "code", 363 | "execution_count": 9, 364 | "metadata": {}, 365 | "outputs": [], 366 | "source": [ 367 | "url = URL + 'me/drive/items/C1465DBECD7188C9!106/children/'\n", 368 | "data = {\n", 369 | " \"name\": \"sub_folder\",\n", 370 | " \"folder\": {},\n", 371 | " \"@microsoft.graph.conflictBehavior\": \"rename\"\n", 372 | "}\n", 373 | "\n", 374 | "response = json.loads(requests.post(url, headers=HEADERS, json = data).text)" 375 | ] 376 | }, 377 | { 378 | "cell_type": "markdown", 379 | "metadata": {}, 380 | "source": [ 381 | "Now let's print the list again. " 382 | ] 383 | }, 384 | { 385 | "cell_type": "code", 386 | "execution_count": 10, 387 | "metadata": {}, 388 | "outputs": [ 389 | { 390 | "name": "stdout", 391 | "output_type": "stream", 392 | "text": [ 393 | "sub_folder | item-id > C1465DBECD7188C9!107\n" 394 | ] 395 | } 396 | ], 397 | "source": [ 398 | "url = URL + 'me/drive/items/C1465DBECD7188C9!106/children'\n", 399 | "items = json.loads(requests.get(url, headers=HEADERS).text)\n", 400 | "items = items['value']\n", 401 | "for entries in range(len(items)):\n", 402 | " print(items[entries]['name'], '| item-id >', items[entries]['id'])" 403 | ] 404 | }, 405 | { 406 | "cell_type": "markdown", 407 | "metadata": {}, 408 | "source": [ 409 | "### Move itme" 410 | ] 411 | }, 412 | { 413 | "cell_type": "code", 414 | "execution_count": null, 415 | "metadata": {}, 416 | "outputs": [], 417 | "source": [ 418 | "# url = URL + 'me/drive/items/{item-id-of-item-to-be-moved}'\n", 419 | "# provide item-id-of-destination-directory under parentReference in the body\n", 420 | "url = URL + 'me/drive/items/C1465DBECD7188C9!106'\n", 421 | "body = {\n", 422 | " \"parentReference\": {\n", 423 | " \"id\": \"C1465DBECD7188C9!103\"\n", 424 | " },\n", 425 | "}\n", 426 | "response = json.loads(requests.patch(url, headers=HEADERS, json=body).text)" 427 | ] 428 | }, 429 | { 430 | "cell_type": "markdown", 431 | "metadata": {}, 432 | "source": [ 433 | "### Rename an item" 434 | ] 435 | }, 436 | { 437 | "cell_type": "code", 438 | "execution_count": 11, 439 | "metadata": {}, 440 | "outputs": [], 441 | "source": [ 442 | "url = URL + 'me/drive/items/C1465DBECD7188C9!106'\n", 443 | "body = {\n", 444 | " \"name\": \"New_folder_2\",\n", 445 | "}\n", 446 | "response = json.loads(requests.patch(url, headers=HEADERS, json = body).text)" 447 | ] 448 | }, 449 | { 450 | "cell_type": "code", 451 | "execution_count": 13, 452 | "metadata": {}, 453 | "outputs": [ 454 | { 455 | "name": "stdout", 456 | "output_type": "stream", 457 | "text": [ 458 | "Documents | item-id > C1465DBECD7188C9!103\n", 459 | "New_folder_2 | item-id > C1465DBECD7188C9!106\n", 460 | "Pictures | item-id > C1465DBECD7188C9!104\n", 461 | "Getting started with OneDrive.pdf | item-id > C1465DBECD7188C9!102\n" 462 | ] 463 | } 464 | ], 465 | "source": [ 466 | "url = URL + 'me/drive/items/root/children'\n", 467 | "items = json.loads(requests.get(url, headers=HEADERS).text)\n", 468 | "items = items['value']\n", 469 | "for entries in range(len(items)):\n", 470 | " print(items[entries]['name'], '| item-id >', items[entries]['id'])" 471 | ] 472 | }, 473 | { 474 | "cell_type": "markdown", 475 | "metadata": {}, 476 | "source": [ 477 | "#### Delete item" 478 | ] 479 | }, 480 | { 481 | "cell_type": "code", 482 | "execution_count": 14, 483 | "metadata": {}, 484 | "outputs": [ 485 | { 486 | "name": "stdout", 487 | "output_type": "stream", 488 | "text": [ 489 | "Are you sure to delete the Item? (Y/n):y\n", 490 | "Item gone! If need to recover, please check OneDrive Recycle Bin.\n" 491 | ] 492 | } 493 | ], 494 | "source": [ 495 | "url = '/me/drive/items/C1465DBECD7188C9!106'\n", 496 | "url = URL + url\n", 497 | "confirmation = input('Are you sure to delete the Item? (Y/n):')\n", 498 | "if (confirmation.lower()=='y'): \n", 499 | " response = requests.delete(url, headers=HEADERS)\n", 500 | " if (response.status_code == 204):\n", 501 | " print('Item gone! If need to recover, please check OneDrive Recycle Bin.')\n", 502 | "else: \n", 503 | " print(\"Item not deleted.\")" 504 | ] 505 | }, 506 | { 507 | "cell_type": "code", 508 | "execution_count": 15, 509 | "metadata": {}, 510 | "outputs": [ 511 | { 512 | "name": "stdout", 513 | "output_type": "stream", 514 | "text": [ 515 | "Documents | item-id > C1465DBECD7188C9!103\n", 516 | "Pictures | item-id > C1465DBECD7188C9!104\n", 517 | "Getting started with OneDrive.pdf | item-id > C1465DBECD7188C9!102\n" 518 | ] 519 | } 520 | ], 521 | "source": [ 522 | "url = URL + 'me/drive/items/root/children'\n", 523 | "items = json.loads(requests.get(url, headers=HEADERS).text)\n", 524 | "items = items['value']\n", 525 | "for entries in range(len(items)):\n", 526 | " print(items[entries]['name'], '| item-id >', items[entries]['id'])" 527 | ] 528 | }, 529 | { 530 | "cell_type": "markdown", 531 | "metadata": {}, 532 | "source": [ 533 | "#### Find item-id by item name" 534 | ] 535 | }, 536 | { 537 | "cell_type": "code", 538 | "execution_count": 17, 539 | "metadata": {}, 540 | "outputs": [ 541 | { 542 | "name": "stdout", 543 | "output_type": "stream", 544 | "text": [ 545 | "Item-id of Documents : C1465DBECD7188C9!103\n" 546 | ] 547 | } 548 | ], 549 | "source": [ 550 | "items = json.loads(requests.get(URL + 'me/drive/items/root/children', headers=HEADERS).text)\n", 551 | "look_for_item = 'Documents'\n", 552 | "item_id = ''\n", 553 | "items = items['value']\n", 554 | "for entries in range(len(items)):\n", 555 | " if(items[entries]['name'] == look_for_item):\n", 556 | " item_id = items[entries]['id']\n", 557 | " print('Item-id of', look_for_item, ':', item_id)\n", 558 | " break\n", 559 | "if(item_id==''):\n", 560 | " print(look_for_item, 'not found in the directory.')" 561 | ] 562 | }, 563 | { 564 | "cell_type": "markdown", 565 | "metadata": {}, 566 | "source": [ 567 | "#### Upload file" 568 | ] 569 | }, 570 | { 571 | "cell_type": "code", 572 | "execution_count": 18, 573 | "metadata": {}, 574 | "outputs": [], 575 | "source": [ 576 | "url = 'me/drive/root:/example_spectrum.txt:/content'\n", 577 | "url = URL + url\n", 578 | "content = open('example_spectrum.txt', 'rb')\n", 579 | "response = json.loads(requests.put(url, headers=HEADERS, data = content).text)" 580 | ] 581 | }, 582 | { 583 | "cell_type": "code", 584 | "execution_count": 19, 585 | "metadata": {}, 586 | "outputs": [ 587 | { 588 | "name": "stdout", 589 | "output_type": "stream", 590 | "text": [ 591 | "Documents | item-id > C1465DBECD7188C9!103\n", 592 | "Pictures | item-id > C1465DBECD7188C9!104\n", 593 | "example_spectrum.txt | item-id > C1465DBECD7188C9!108\n", 594 | "Getting started with OneDrive.pdf | item-id > C1465DBECD7188C9!102\n" 595 | ] 596 | } 597 | ], 598 | "source": [ 599 | "url = URL + 'me/drive/items/root/children'\n", 600 | "items = json.loads(requests.get(url, headers=HEADERS).text)\n", 601 | "items = items['value']\n", 602 | "for entries in range(len(items)):\n", 603 | " print(items[entries]['name'], '| item-id >', items[entries]['id'])" 604 | ] 605 | }, 606 | { 607 | "cell_type": "markdown", 608 | "metadata": {}, 609 | "source": [ 610 | "### Access/Download data" 611 | ] 612 | }, 613 | { 614 | "cell_type": "code", 615 | "execution_count": 22, 616 | "metadata": {}, 617 | "outputs": [], 618 | "source": [ 619 | "url = 'me/drive/root:/example_spectrum.txt:/content'\n", 620 | "url = URL + url\n", 621 | "data = requests.get(url, headers=HEADERS).text" 622 | ] 623 | }, 624 | { 625 | "cell_type": "markdown", 626 | "metadata": {}, 627 | "source": [ 628 | "You may like to save the data in a file in your local drive. " 629 | ] 630 | }, 631 | { 632 | "cell_type": "markdown", 633 | "metadata": {}, 634 | "source": [ 635 | "#### Upload large files (Can be used to upload small files as well)\n", 636 | "If you have files (probably larger than 4 MB), you need to create upload sessions." 637 | ] 638 | }, 639 | { 640 | "cell_type": "code", 641 | "execution_count": 11, 642 | "metadata": {}, 643 | "outputs": [], 644 | "source": [ 645 | "url = 'me/drive/items/C1465DBECD7188C9!103:/large_file.dat:/createUploadSession'\n", 646 | "url = URL + url\n", 647 | "url = json.loads(requests.post(url, headers=HEADERS).text)\n", 648 | "url = url['uploadUrl']\n", 649 | "file_path = '/local/file/path/large_file.dat'\n", 650 | "file_size = os.path.getsize(file_path)\n", 651 | "chunk_size = 320*1024*10 # Has to be multiple of 320 kb\n", 652 | "no_of_uploads = file_size//chunk_size\n", 653 | "content_range_start = 0\n", 654 | "if file_size < chunk_size : \n", 655 | " content_range_end = file_size\n", 656 | "else :\n", 657 | " content_range_end = chunk_size - 1\n", 658 | "\n", 659 | "data = open(file_path, 'rb')\n", 660 | "while data.tell() < file_size:\n", 661 | " if ((file_size - data.tell()) <= chunk_size):\n", 662 | " content_range_end = file_size -1\n", 663 | " headers = {'Content-Range' : 'bytes '+ str(content_range_start)+ '-' +str(content_range_end)+'/'+str(file_size)}\n", 664 | " content = data.read(chunk_size)\n", 665 | " response = json.loads(requests.put(url, headers=headers, data = content).text)\n", 666 | " else:\n", 667 | " headers = {'Content-Range' : 'bytes '+ str(content_range_start)+ '-' +str(content_range_end)+'/'+str(file_size)}\n", 668 | " content = data.read(chunk_size)\n", 669 | " response = json.loads(requests.put(url, headers=headers, data = content).text)\n", 670 | " content_range_start = data.tell()\n", 671 | " content_range_end = data.tell() + chunk_size - 1\n", 672 | "data.close()\n", 673 | "response2 = requests.delete(url)" 674 | ] 675 | }, 676 | { 677 | "cell_type": "markdown", 678 | "metadata": {}, 679 | "source": [ 680 | "#### OneDrive storage usage" 681 | ] 682 | }, 683 | { 684 | "cell_type": "code", 685 | "execution_count": 12, 686 | "metadata": {}, 687 | "outputs": [ 688 | { 689 | "name": "stdout", 690 | "output_type": "stream", 691 | "text": [ 692 | "Using 0.48 GB ( 9.6 %) of total 5.0 GB.\n" 693 | ] 694 | } 695 | ], 696 | "source": [ 697 | "response = json.loads(requests.get(URL + 'me/drive/', headers = HEADERS).text)\n", 698 | "used = round(response['quota']['used']/(1024*1024*1024), 2)\n", 699 | "total = round(response['quota']['total']/(1024*1024*1024), 2)\n", 700 | "print('Using', used, 'GB (', round(used*100/total, 2),'%) of total', total, 'GB.')" 701 | ] 702 | }, 703 | { 704 | "cell_type": "code", 705 | "execution_count": null, 706 | "metadata": {}, 707 | "outputs": [], 708 | "source": [] 709 | } 710 | ], 711 | "metadata": { 712 | "kernelspec": { 713 | "display_name": "Python 3", 714 | "language": "python", 715 | "name": "python3" 716 | }, 717 | "language_info": { 718 | "codemirror_mode": { 719 | "name": "ipython", 720 | "version": 3 721 | }, 722 | "file_extension": ".py", 723 | "mimetype": "text/x-python", 724 | "name": "python", 725 | "nbconvert_exporter": "python", 726 | "pygments_lexer": "ipython3", 727 | "version": "3.7.3" 728 | } 729 | }, 730 | "nbformat": 4, 731 | "nbformat_minor": 2 732 | } 733 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Access OneDrive via Graph API (Python code) 2 | Upload, download, rename your files and many more to your OneDrive both personal 3 | and business accounts using Microsoft Graph API (Python code). 4 | 5 | First you need to [register your app](Azure_app_signup_step_by_step.md) in the 6 | Azure portal. 7 | 8 | ```python 9 | # Program: Accessing OneDrive via Graph API 10 | # Author: Pranab Das (GitHub: @pranabdas) 11 | # Version: 20210820 12 | ``` 13 | 14 | ```python 15 | # requirements 16 | import requests 17 | import json 18 | import urllib 19 | import os 20 | from getpass import getpass 21 | import time 22 | from datetime import datetime 23 | ``` 24 | 25 | 26 | ## Get Access token 27 | 28 | ### Token flow authentication 29 | 30 | ```python 31 | URL = 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize' 32 | client_id = "362422eb-d9d6-4245-9eca-2be5cf256450" 33 | permissions = ['files.readwrite'] 34 | response_type = 'token' 35 | redirect_uri = 'http://localhost:8080/' 36 | scope = '' 37 | for items in range(len(permissions)): 38 | scope = scope + permissions[items] 39 | if items < len(permissions)-1: 40 | scope = scope + '+' 41 | 42 | print('Click over this link ' +URL + '?client_id=' + client_id + '&scope=' + scope + '&response_type=' + response_type+\ 43 | '&redirect_uri=' + urllib.parse.quote(redirect_uri)) 44 | print('Sign in to your account, copy the whole redirected URL.') 45 | code = input("Paste the URL here :") 46 | token = code[(code.find('access_token') + len('access_token') + 1) : (code.find('&token_type'))] 47 | URL = 'https://graph.microsoft.com/v1.0/' 48 | HEADERS = {'Authorization': 'Bearer ' + token} 49 | response = requests.get(URL + 'me/drive/', headers = HEADERS) 50 | if (response.status_code == 200): 51 | response = json.loads(response.text) 52 | print('Connected to the OneDrive of', response['owner']['user']['displayName']+' (',response['driveType']+' ).', \ 53 | '\nConnection valid for one hour. Reauthenticate if required.') 54 | elif (response.status_code == 401): 55 | response = json.loads(response.text) 56 | print('API Error! : ', response['error']['code'],\ 57 | '\nSee response for more details.') 58 | else: 59 | response = json.loads(response.text) 60 | print('Unknown error! See response for more details.') 61 | ``` 62 | 63 | Click over this link https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=362422eb-d9d6-4245-9eca-2be5cf256450&scope=files.readwrite&response_type=token&redirect_uri=http%3A//localhost%3A8080/ 64 | Sign in to your account, copy the whole redirected URL. 65 | Paste the URL here :http://localhost:8080/#access_token=EwBYA8l6BAAUO9chh8cJscQLmU%2bLSWpbnr0vmwwAAXbgH8Q919pMC8ErHXfcrM/uuPvmmsIyKar8nmAp1mvv/0QwrjAkSBM8Y6sJqpPEPrGKBrDHairoIVrQK7FhGCtYLGEy3P88wnaKGr4NYygckbi2g6P4S5KPt7d3m3/7XuAhLips6jwD3X8g89a72SajQaa1xbPFw2TfUed/UG6kqUxzlVUy4gkPCBMm%2bizQ3mP7lXRbmeXqCY5omTSQz6djvkCcjXf9TqC1WfVpRLHGc7yLUPcg15nGmdMfwRxWDxYi8rlD34Y0cVYt4KYw3B2VkdxyMvCWqARgauWApLYTFopGZIUQ8M0Fggb89PncdhHInKehD8Rp7rkBJIhkfIIDZgAACBnA%2btK5eKnhKAJmVnI6%2b2MwF54q9NR04O9xTn0Py/uOJPpyGeAtMRBgHTSI6Eh/Bwr/ybQh2TMbfNBbqpOEjPYx0KDhDhrcS1LldJKKoYj2EOREEkwKZNKYfmTdO1jWQ/MohoOFawGB29gdSyJxkqgRHrC2RedL3wFYMOxE78ehVvfCl1/UqBR4Z4ypPMZ%2bsFlyCOCQ6E2fiLyJt0AF5wZencLGoAhXdlh/gIDVZuSZBVQXZuEP19d07IGqLmwDoVnhecniQMjy3cLVQ5v0vlT15b/GpuESNhtgrdQwGT307F9gHPVO6U9UMzfT1iEx%2bjqOBR5paJz8OiIZOG3SZmqZFB4c606Vycio3BVnkXyNlf6kBZfJMNVLB4IubmXSbM%2byFjadP1Cq3pc2dsQRx%2bMqhYCDYS%2bYm4yBqHW0r/XfLrs/QmiIgVtAneHyw99TYVFEO2sqM3MLPZS1W8Wm0cFvwvfxuDI4cDllhjkX5jPy0wSD35c9rDZ8gwWdpR1x6Xc/XaTsn1eQEb9CcsZxyyIeJ6SA9t2kysZ1udqbu4xqIuMt3QtIdYA3tDDIg9IPJtF7tuC48G5tjm7BlfOANxhfsg8USYtjovd3KC4Jl4w87OBeiGrRQgaoI4pEfZVgYPa4TuOYe6ZuYCEyNW8GYumvetzmkRkrMBwicAqJ5KXVco5Lird6gCbQSWFjBTfxtdzXFKCiEgcQSDAm88xTwN2LvBKsrbV17QkEyNYqcVzo1CdsAg%3d%3d&token_type=bearer&expires_in=3600&scope=Files.ReadWrite%20Files.ReadWrite.All 66 | Connected to the OneDrive of ( personal ). 67 | Connection valid for one hour. Reauthenticate if required. 68 | 69 | 70 | Looks all right. We have got the access token, and included in the HEADERS. You 71 | can print response to see more. Go ahead with OneDrive operations. 72 | 73 | ### Code flow authentication 74 | 75 | Code flow returns both `access_token` and `refresh_token` which can be used to 76 | request new `access_token` and `refresh_token` for persistent session. If you 77 | are using organization account, you might require consent of organization 78 | administrator. 79 | 80 | ```python 81 | # Get code 82 | URL = 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize' 83 | client_id = "362422eb-d9d6-4245-9eca-2be5cf256450" 84 | permissions = ['offline_access', 'files.readwrite', 'User.Read'] 85 | response_type = 'code' 86 | redirect_uri = 'http://localhost:8080/' 87 | scope = '' 88 | for items in range(len(permissions)): 89 | scope = scope + permissions[items] 90 | if items < len(permissions)-1: 91 | scope = scope + '+' 92 | 93 | print('Click over this link ' +URL + '?client_id=' + client_id + '&scope=' + scope + '&response_type=' + response_type+\ 94 | '&redirect_uri=' + urllib.parse.quote(redirect_uri)) 95 | print('Sign in to your account, copy the whole redirected URL.') 96 | code = getpass("Paste the URL here :") 97 | code = code[(code.find('?code') + len('?code') + 1) :] 98 | 99 | URL = 'https://login.microsoftonline.com/common/oauth2/v2.0/token' 100 | 101 | response = requests.post(URL + '?client_id=' + client_id + '&scope=' + scope + '&grant_type=authorization_code' +\ 102 | '&redirect_uri=' + urllib.parse.quote(redirect_uri)+ '&code=' + code) 103 | ``` 104 | 105 | ```python 106 | # Get token 107 | data = { 108 | "client_id": client_id, 109 | "scope": permissions, 110 | "code": code, 111 | "redirect_uri": redirect_uri, 112 | "grant_type": 'authorization_code', 113 | "client_secret": client_secret 114 | } 115 | 116 | response = requests.post(URL, data=data) 117 | 118 | token = json.loads(response.text)["access_token"] 119 | refresh_token = json.loads(response.text)["refresh_token"] 120 | ``` 121 | 122 | ```python 123 | # Refresh token 124 | def get_refresh_token(): 125 | data = { 126 | "client_id": client_id, 127 | "scope": permissions, 128 | "refresh_token": refresh_token, 129 | "redirect_uri": redirect_uri, 130 | "grant_type": 'refresh_token', 131 | "client_secret": 'xxxx-yyyy-zzzz', 132 | } 133 | 134 | response = requests.post(URL, data=data) 135 | 136 | token = json.loads(response.text)["access_token"] 137 | refresh_token = json.loads(response.text)["refresh_token"] 138 | last_updated = time.mktime(datetime.today().timetuple()) 139 | 140 | return token, refresh_token, last_updated 141 | ``` 142 | 143 | ```python 144 | token, refresh_token, last_updated = get_refresh_token() 145 | ``` 146 | 147 | If you have a large data to upload, you may use below mock code inside your 148 | upload loop: 149 | ```python 150 | elapsed_time = time.mktime(datetime.today().timetuple()) - last_updated 151 | 152 | if (elapsed_time < 45*60*60): 153 | do_something() 154 | else if (elapsed_time < 59*60*60): 155 | token, refresh_token, last_updated = get_refresh_token() 156 | else: 157 | go_to_code_flow() 158 | ``` 159 | 160 | ## OneDrive operations 161 | 162 | ```python 163 | URL = 'https://graph.microsoft.com/v1.0/' 164 | 165 | HEADERS = {'Authorization': 'Bearer ' + token} 166 | 167 | response = requests.get(URL + 'me/drive/', headers = HEADERS) 168 | if (response.status_code == 200): 169 | response = json.loads(response.text) 170 | print('Connected to the OneDrive of', response['owner']['user']['displayName']+' (',response['driveType']+' ).', \ 171 | '\nConnection valid for one hour. Refresh token if required.') 172 | elif (response.status_code == 401): 173 | response = json.loads(response.text) 174 | print('API Error! : ', response['error']['code'],\ 175 | '\nSee response for more details.') 176 | else: 177 | response = json.loads(response.text) 178 | print('Unknown error! See response for more details.') 179 | ``` 180 | 181 | ### List folders under root directory 182 | 183 | We will print both directory `name` and `item-d` 184 | ```python 185 | items = json.loads(requests.get(URL + 'me/drive/root/children', headers=HEADERS).text) 186 | items = items['value'] 187 | for entries in range(len(items)): 188 | print(items[entries]['name'], '| item-id >', items[entries]['id']) 189 | ``` 190 | 191 | Documents | item-id > C1465DBECD7188C9!103 192 | Pictures | item-id > C1465DBECD7188C9!104 193 | Getting started with OneDrive.pdf | item-id > C1465DBECD7188C9!102 194 | 195 | 196 | ### Create new folder (in the root directory) 197 | 198 | ```python 199 | url = URL + 'me/drive/root/children/' 200 | body = { 201 | "name": "New_Folder", 202 | "folder": {}, 203 | "@microsoft.graph.conflictBehavior": "rename" 204 | } 205 | response = json.loads(requests.post(url, headers=HEADERS, json=body).text) 206 | ``` 207 | 208 | Now lets list the directory again: 209 | 210 | ```python 211 | items = json.loads(requests.get(URL + 'me/drive/root/children', headers=HEADERS).text) 212 | items = items['value'] 213 | for entries in range(len(items)): 214 | print(items[entries]['name'], '| item-id >', items[entries]['id']) 215 | ``` 216 | 217 | Documents | item-id > C1465DBECD7188C9!103 218 | New_Folder | item-id > C1465DBECD7188C9!106 219 | Pictures | item-id > C1465DBECD7188C9!104 220 | Getting started with OneDrive.pdf | item-id > C1465DBECD7188C9!102 221 | 222 | 223 | Here we go, we have successfully created the folder New_Folder. 224 | 225 | 226 | ### List folders under a sub-folder (need to use item-id) 227 | Note that if you need to create or list sub-folders, you need to use the 228 | `item-id`. The `path/folder` notation does not work everywhere. 229 | 230 | 231 | ```python 232 | url = URL + 'me/drive/items/C1465DBECD7188C9!106/children' 233 | items = json.loads(requests.get(url, headers=HEADERS).text) 234 | items = items['value'] 235 | for entries in range(len(items)): 236 | print(items[entries]['name'], '| item-id >', items[entries]['id']) 237 | ``` 238 | 239 | Well there are no files or folders under the `New_Folder`. Ok let's create one. 240 | 241 | ```python 242 | url = URL + 'me/drive/items/C1465DBECD7188C9!106/children/' 243 | data = { 244 | "name": "sub_folder", 245 | "folder": {}, 246 | "@microsoft.graph.conflictBehavior": "rename" 247 | } 248 | 249 | response = json.loads(requests.post(url, headers=HEADERS, json = data).text) 250 | ``` 251 | 252 | Now let's print the list again. 253 | 254 | ```python 255 | url = URL + 'me/drive/items/C1465DBECD7188C9!106/children' 256 | items = json.loads(requests.get(url, headers=HEADERS).text) 257 | items = items['value'] 258 | for entries in range(len(items)): 259 | print(items[entries]['name'], '| item-id >', items[entries]['id']) 260 | ``` 261 | 262 | sub_folder | item-id > C1465DBECD7188C9!107 263 | 264 | 265 | ### Rename an item 266 | 267 | ```python 268 | url = URL + 'me/drive/items/C1465DBECD7188C9!106' 269 | body = { 270 | "name": "New_folder_2", 271 | } 272 | response = json.loads(requests.patch(url, headers=HEADERS, json = body).text) 273 | ``` 274 | 275 | ```python 276 | url = URL + 'me/drive/items/root/children' 277 | items = json.loads(requests.get(url, headers=HEADERS).text) 278 | items = items['value'] 279 | for entries in range(len(items)): 280 | print(items[entries]['name'], '| item-id >', items[entries]['id']) 281 | ``` 282 | 283 | Documents | item-id > C1465DBECD7188C9!103 284 | New_folder_2 | item-id > C1465DBECD7188C9!106 285 | Pictures | item-id > C1465DBECD7188C9!104 286 | Getting started with OneDrive.pdf | item-id > C1465DBECD7188C9!102 287 | 288 | 289 | ### Move item 290 | ```python 291 | # url = URL + 'me/drive/items/{item-id-of-item-to-be-moved}' 292 | # provide item-id-of-destination-directory under parentReference in the body 293 | url = URL + 'me/drive/items/C1465DBECD7188C9!106' 294 | body = { 295 | "parentReference": { 296 | "id": "C1465DBECD7188C9!103" 297 | }, 298 | } 299 | response = json.loads(requests.patch(url, headers=HEADERS, json=body).text) 300 | ``` 301 | 302 | 303 | ### Delete item 304 | 305 | ```python 306 | url = '/me/drive/items/C1465DBECD7188C9!106' 307 | url = URL + url 308 | confirmation = input('Are you sure to delete the Item? (Y/n):') 309 | if (confirmation.lower()=='y'): 310 | response = requests.delete(url, headers=HEADERS) 311 | if (response.status_code == 204): 312 | print('Item gone! If need to recover, please check OneDrive Recycle Bin.') 313 | else: 314 | print("Item not deleted.") 315 | ``` 316 | 317 | Are you sure to delete the Item? (Y/n):y 318 | Item gone! If need to recover, please check OneDrive Recycle Bin. 319 | 320 | ```python 321 | url = URL + 'me/drive/items/root/children' 322 | items = json.loads(requests.get(url, headers=HEADERS).text) 323 | items = items['value'] 324 | for entries in range(len(items)): 325 | print(items[entries]['name'], '| item-id >', items[entries]['id']) 326 | ``` 327 | 328 | Documents | item-id > C1465DBECD7188C9!103 329 | Pictures | item-id > C1465DBECD7188C9!104 330 | Getting started with OneDrive.pdf | item-id > C1465DBECD7188C9!102 331 | 332 | 333 | ### Find item-id by item name 334 | 335 | ```python 336 | items = json.loads(requests.get(URL + 'me/drive/items/root/children', headers=HEADERS).text) 337 | look_for_item = 'Documents' 338 | item_id = '' 339 | items = items['value'] 340 | for entries in range(len(items)): 341 | if(items[entries]['name'] == look_for_item): 342 | item_id = items[entries]['id'] 343 | print('Item-id of', look_for_item, ':', item_id) 344 | break 345 | if(item_id==''): 346 | print(look_for_item, 'not found in the directory.') 347 | ``` 348 | 349 | Item-id of Documents : C1465DBECD7188C9!103 350 | 351 | 352 | ### Upload file 353 | 354 | ```python 355 | url = 'me/drive/root:/example_spectrum.txt:/content' 356 | url = URL + url 357 | content = open('example_spectrum.txt', 'rb') 358 | response = json.loads(requests.put(url, headers=HEADERS, data = content).text) 359 | ``` 360 | 361 | 362 | ```python 363 | url = URL + 'me/drive/items/root/children' 364 | items = json.loads(requests.get(url, headers=HEADERS).text) 365 | items = items['value'] 366 | for entries in range(len(items)): 367 | print(items[entries]['name'], '| item-id >', items[entries]['id']) 368 | ``` 369 | 370 | Documents | item-id > C1465DBECD7188C9!103 371 | Pictures | item-id > C1465DBECD7188C9!104 372 | example_spectrum.txt | item-id > C1465DBECD7188C9!108 373 | Getting started with OneDrive.pdf | item-id > C1465DBECD7188C9!102 374 | 375 | 376 | ### Access/Download data 377 | 378 | ```python 379 | url = 'me/drive/root:/example_spectrum.txt:/content' 380 | url = URL + url 381 | data = requests.get(url, headers=HEADERS).text 382 | ``` 383 | 384 | You may like to save the data in a file in your local drive. 385 | 386 | 387 | ### Upload large files (Can be used to upload small files as well) 388 | If you have files (probably larger than 4 MB), you need to create upload 389 | sessions. 390 | 391 | 392 | ```python 393 | url = 'me/drive/items/C1465DBECD7188C9!103:/large_file.dat:/createUploadSession' 394 | url = URL + url 395 | url = json.loads(requests.post(url, headers=HEADERS).text) 396 | url = url['uploadUrl'] 397 | file_path = '/local/file/path/large_file.dat' 398 | file_size = os.path.getsize(file_path) 399 | chunk_size = 320*1024*10 # Has to be multiple of 320 kb 400 | no_of_uploads = file_size//chunk_size 401 | content_range_start = 0 402 | if file_size < chunk_size : 403 | content_range_end = file_size 404 | else : 405 | content_range_end = chunk_size - 1 406 | 407 | data = open(file_path, 'rb') 408 | while data.tell() < file_size: 409 | if ((file_size - data.tell()) <= chunk_size): 410 | content_range_end = file_size -1 411 | headers = {'Content-Range' : 'bytes '+ str(content_range_start)+ '-' +str(content_range_end)+'/'+str(file_size)} 412 | content = data.read(chunk_size) 413 | response = json.loads(requests.put(url, headers=headers, data = content).text) 414 | else: 415 | headers = {'Content-Range' : 'bytes '+ str(content_range_start)+ '-' +str(content_range_end)+'/'+str(file_size)} 416 | content = data.read(chunk_size) 417 | response = json.loads(requests.put(url, headers=headers, data = content).text) 418 | content_range_start = data.tell() 419 | content_range_end = data.tell() + chunk_size - 1 420 | data.close() 421 | response2 = requests.delete(url) 422 | ``` 423 | 424 | 425 | ### OneDrive storage usage 426 | 427 | ```python 428 | response = json.loads(requests.get(URL + 'me/drive/', headers = HEADERS).text) 429 | used = round(response['quota']['used']/(1024*1024*1024), 2) 430 | total = round(response['quota']['total']/(1024*1024*1024), 2) 431 | print('Using', used, 'GB (', round(used*100/total, 2),'%) of total', total, 'GB.') 432 | ``` 433 | 434 | Using 0.48 GB ( 9.6 %) of total 5.0 GB. 435 | -------------------------------------------------------------------------------- /assets/01.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pranabdas/Access-OneDrive-via-Microsoft-Graph-Python/055fa6df3d79c42fd217b47c7fba5c4bb6aab274/assets/01.PNG -------------------------------------------------------------------------------- /assets/02.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pranabdas/Access-OneDrive-via-Microsoft-Graph-Python/055fa6df3d79c42fd217b47c7fba5c4bb6aab274/assets/02.PNG -------------------------------------------------------------------------------- /assets/03.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pranabdas/Access-OneDrive-via-Microsoft-Graph-Python/055fa6df3d79c42fd217b47c7fba5c4bb6aab274/assets/03.PNG -------------------------------------------------------------------------------- /assets/04.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pranabdas/Access-OneDrive-via-Microsoft-Graph-Python/055fa6df3d79c42fd217b47c7fba5c4bb6aab274/assets/04.PNG -------------------------------------------------------------------------------- /assets/05.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pranabdas/Access-OneDrive-via-Microsoft-Graph-Python/055fa6df3d79c42fd217b47c7fba5c4bb6aab274/assets/05.PNG -------------------------------------------------------------------------------- /assets/06.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pranabdas/Access-OneDrive-via-Microsoft-Graph-Python/055fa6df3d79c42fd217b47c7fba5c4bb6aab274/assets/06.PNG -------------------------------------------------------------------------------- /assets/07.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pranabdas/Access-OneDrive-via-Microsoft-Graph-Python/055fa6df3d79c42fd217b47c7fba5c4bb6aab274/assets/07.PNG -------------------------------------------------------------------------------- /assets/08.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pranabdas/Access-OneDrive-via-Microsoft-Graph-Python/055fa6df3d79c42fd217b47c7fba5c4bb6aab274/assets/08.PNG -------------------------------------------------------------------------------- /assets/09.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pranabdas/Access-OneDrive-via-Microsoft-Graph-Python/055fa6df3d79c42fd217b47c7fba5c4bb6aab274/assets/09.PNG -------------------------------------------------------------------------------- /assets/10.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pranabdas/Access-OneDrive-via-Microsoft-Graph-Python/055fa6df3d79c42fd217b47c7fba5c4bb6aab274/assets/10.PNG --------------------------------------------------------------------------------