Chilkat HOME .NET Core C# Android™ AutoIt C C# C++ Chilkat2-Python CkPython Classic ASP DataFlex Delphi ActiveX Delphi DLL Go Java Lianja Mono C# Node.js Objective-C PHP ActiveX PHP Extension Perl PowerBuilder PowerShell PureBasic Ruby SQL Server Swift 2 Swift 3,4,5... Tcl Unicode C Unicode C++ VB.NET VBScript Visual Basic 6.0 Visual FoxPro Xojo Plugin
(Tcl) Google Drive - Build a Local Cache of MetadataThis example demonstrates how to download the metadata for all files in a Google Drive account to create a local filesystem cache with the information. The cache can be used to fetch information without having to query Google Drive.
load ./chilkat.dll set success 1 # It requires the Chilkat API to have been previously unlocked. # See Global Unlock Sample for sample code. # This example uses a previously obtained access token having permission for the # Google Drive scope. set gAuth [new_CkAuthGoogle] CkAuthGoogle_put_AccessToken $gAuth "GOOGLE_DRIVE_ACCESS_TOKEN" set rest [new_CkRest] # Connect using TLS. set bAutoReconnect 1 set success [CkRest_Connect $rest "www.googleapis.com" 443 1 $bAutoReconnect] # Provide the authentication credentials (i.e. the access token) CkRest_SetAuthGoogle $rest $gAuth # ------------------------------------------------------------------- # Initialize our cache object. Indicate the location of the root cache directory, and how many cache levels are to exist. # For small caches (level 0) all cache files are in the root directory. # For medium caches (level 1) cache files are located in 256 sub-directories from the root. # For large caches (level 2) cache files are located in 256x256 sub-directories two levels down from the root. set gdCache [new_CkCache] CkCache_put_Level $gdCache 0 # Use a root directory that makes sense on your operating system.. CkCache_AddRoot $gdCache "C:/ckCache/googleDrive" # If we are re-building the cache, we can first delete the entire contents of the cache. set numCacheFilesDeleted [CkCache_DeleteAll $gdCache] # Create a date/time object with an time 7 days from the current date/time. set dtExpire [new_CkDateTime] CkDateTime_SetFromCurrentSystemTime $dtExpire CkDateTime_AddDays $dtExpire 7 # Indicate that we want ALL possible fields. # If no fields are indicated, then only the basic fields are returned. set allFields "appProperties,capabilities,contentHints,createdTime,description,explicitlyTrashed,fileExtension,folderColorRgb,fullFileExtension,headRevisionId,iconLink,id,imageMediaMetadata,isAppAuthorized,kind,lastModifyingUser,md5Checksum,mimeType,modifiedByMeTime,modifiedTime,name,originalFilename,ownedByMe,owners,parents,permissions,properties,quotaBytesUsed,shared,sharedWithMeTime,sharingUser,size,spaces,starred,thumbnailLink,trashed,version,videoMediaMetadata,viewedByMe,viewedByMeTime,viewersCanCopyContent,webContentLink,webViewLink,writersCanShare" # We're going to keep a master list of fileId's as we iterate over all the files in this Google Drive account. # This master list will also be saved to the cache under the key "AllGoogleDriveFileIds". set jsonMaster [new_CkJsonObject] # jsonMasterArr is a CkJsonArray set jsonMasterArr [CkJsonObject_AppendArray $jsonMaster "fileIds"] # Also keep a list of file paths. # jsonMasterPaths is a CkJsonArray set jsonMasterPaths [CkJsonObject_AppendArray $jsonMaster "filePaths"] # The default page size is 100, with a max of 1000. CkRest_AddQueryParam $rest "pageSize" "200" set json [new_CkJsonObject] # jsonFileMetadata is a CkJsonObject # Send the request for the 1st page. set jsonResponse [CkRest_fullRequestNoBody $rest "GET" "/drive/v3/files"] set pageNumber 1 set bContinueLoop [expr [CkRest_get_LastMethodSuccess $rest] && [[CkRest_get_ResponseStatusCode $rest] == 200]] while {$bContinueLoop == 1} { puts "---- Page $pageNumber ----" CkJsonObject_Load $json $jsonResponse set numFiles [CkJsonObject_SizeOfArray $json "files"] set i 0 while {$i < $numFiles} { # Add this file ID to the master list. CkJsonObject_put_I $json $i CkJsonArray_AddStringAt $jsonMasterArr -1 [CkJsonObject_stringOf $json "files[i].id"] set i [expr $i + 1] } # Get the next page of files. # If the "nextPageToken" is present in the JSON response, then use it in the "pageToken" parameter # for the next request. If no "nextPageToken" was present, then this was the last page of files. set pageToken [CkJsonObject_stringOf $json "nextPageToken"] set bContinueLoop 0 set bHasMorePages [CkJsonObject_get_LastMethodSuccess $json] if {$bHasMorePages == 1} then { CkRest_ClearAllQueryParams $rest CkRest_AddQueryParam $rest "pageSize" "200" CkRest_AddQueryParam $rest "pageToken" $pageToken set jsonResponse [CkRest_fullRequestNoBody $rest "GET" "/drive/v3/files"] set bContinueLoop [expr [CkRest_get_LastMethodSuccess $rest] && [[CkRest_get_ResponseStatusCode $rest] == 200]] set pageNumber [expr $pageNumber + 1] } } delete_CkJsonArray $jsonMasterArr # Check to see if the above loop exited with errors... if {[CkRest_get_LastMethodSuccess $rest] != 1} then { puts [CkRest_lastErrorText $rest] delete_CkAuthGoogle $gAuth delete_CkRest $rest delete_CkCache $gdCache delete_CkDateTime $dtExpire delete_CkJsonObject $jsonMaster delete_CkJsonObject $json exit } # Check to see if the above loop exited with errors... # A successful response will have a status code equal to 200. if {[CkRest_get_ResponseStatusCode $rest] != 200} then { puts "response status code = [CkRest_get_ResponseStatusCode $rest]" puts "response status text = [CkRest_responseStatusText $rest]" puts "response header: [CkRest_responseHeader $rest]" puts "response JSON: $jsonResponse" delete_CkAuthGoogle $gAuth delete_CkRest $rest delete_CkCache $gdCache delete_CkDateTime $dtExpire delete_CkJsonObject $jsonMaster delete_CkJsonObject $json exit } # Iterate over the file IDs and download the metadata for each, saving each to the cache... # Also, keep in-memory hash entries of the name and parent[0] so we can quickly # build the path-->fileId cache entries. (Given that the Google Drive REST API uses # fileIds, this gives us an easy way to lookup a fileId based on a filePath.) set hashTable [new_CkHashtable] # Set the capacity of the hash table to something reasonable for the number of files # to be hashed. CkHashtable_ClearWithNewCapacity $hashTable 521 set sbPathForFileId [new_CkStringBuilder] # Used for storing the file name and parents[0] in the hashTable. set saFileInfo [new_CkStringArray] CkStringArray_put_Unique $saFileInfo 0 set numFiles [CkJsonObject_SizeOfArray $jsonMaster "fileIds"] set i 0 while {$i < $numFiles} { CkJsonObject_put_I $jsonMaster $i set fileId [CkJsonObject_stringOf $jsonMaster "fileIds[i]"] CkStringBuilder_SetString $sbPathForFileId "/drive/v3/files/" CkStringBuilder_Append $sbPathForFileId $fileId CkRest_ClearAllQueryParams $rest CkRest_AddQueryParam $rest "fields" $allFields set jsonResponse [CkRest_fullRequestNoBody $rest "GET" [CkStringBuilder_getAsString $sbPathForFileId]] if {expr [[CkRest_get_LastMethodSuccess $rest] != 1] || [[CkRest_get_ResponseStatusCode $rest] != 200]} then { # Force an exit of this loop.. set numFiles 0 } # Save this file's metadata to the local cache. # The lookup key is the fileId. CkCache_SaveTextDt $gdCache $fileId $dtExpire "" $jsonResponse # Get this file's name and parent[0], and put this information # in our in-memory hashtable to be used below.. CkJsonObject_Load $json $jsonResponse CkStringArray_Clear $saFileInfo CkStringArray_Append $saFileInfo [CkJsonObject_stringOf $json "name"] CkStringArray_Append $saFileInfo [CkJsonObject_stringOf $json "parents[0]"] CkHashtable_AddStr $hashTable $fileId [CkStringArray_serialize $saFileInfo] puts [CkJsonObject_stringOf $json name], [CkJsonObject_stringOf $json {parents[0]}] set i [expr $i + 1] } # Check to see if the above loop exited with errors... if {[CkRest_get_LastMethodSuccess $rest] != 1} then { puts [CkRest_lastErrorText $rest] delete_CkAuthGoogle $gAuth delete_CkRest $rest delete_CkCache $gdCache delete_CkDateTime $dtExpire delete_CkJsonObject $jsonMaster delete_CkJsonObject $json delete_CkHashtable $hashTable delete_CkStringBuilder $sbPathForFileId delete_CkStringArray $saFileInfo exit } # Check to see if the above loop exited with errors... # A successful response will have a status code equal to 200. if {[CkRest_get_ResponseStatusCode $rest] != 200} then { puts "response status code = [CkRest_get_ResponseStatusCode $rest]" puts "response status text = [CkRest_responseStatusText $rest]" puts "response header: [CkRest_responseHeader $rest]" puts "response JSON: $jsonResponse" delete_CkAuthGoogle $gAuth delete_CkRest $rest delete_CkCache $gdCache delete_CkDateTime $dtExpire delete_CkJsonObject $jsonMaster delete_CkJsonObject $json delete_CkHashtable $hashTable delete_CkStringBuilder $sbPathForFileId delete_CkStringArray $saFileInfo exit } # Now that all the fileId's are in the cache, let's build the directory path # for each fileID. # (Technically, a fileId can have multiple parents, which means it can be in multiple directories # at once. This is only going to build directory paths following the 0'th parent ID in the parents list.) # The directory path for files in "My Drive" will be just the filename. # For files in sub-directories, the path will be relative, such as "subdir1/subdir2/something.pdf" # puts "---- building paths ----" set sbPath [new_CkStringBuilder] set numFiles [CkJsonObject_SizeOfArray $jsonMaster "fileIds"] set i 0 while {$i < $numFiles} { CkJsonObject_put_I $jsonMaster $i CkStringBuilder_Clear $sbPath set fileId [CkJsonObject_stringOf $jsonMaster "fileIds[i]"] set bFinished 0 while {$bFinished == 0} { CkStringArray_Clear $saFileInfo CkStringArray_AppendSerialized $saFileInfo [CkHashtable_lookupStr $hashTable $fileId] # Append this file or directory name. CkStringBuilder_Prepend $sbPath [CkStringArray_getString $saFileInfo 0] # Get the parent fileId set fileId [CkStringArray_getString $saFileInfo 1] # If this fileId is not in the hashtable, then it's the fileId for "My Drive", and we are finished. if {[CkHashtable_Contains $hashTable $fileId] == 0} then { set bFinished 1 } else { CkStringBuilder_Prepend $sbPath "/" } } puts "$i: [CkStringBuilder_getAsString $sbPath]" # Store the filePath --> fileId mapping in our local cache. set fileId [CkJsonObject_stringOf $jsonMaster "fileIds[i]"] CkCache_SaveTextDt $gdCache [CkStringBuilder_getAsString $sbPath] $dtExpire "" $fileId CkJsonArray_AddStringAt $jsonMasterPaths -1 [CkStringBuilder_getAsString $sbPath] set i [expr $i + 1] } delete_CkJsonArray $jsonMasterPaths # Save the master list of file IDs and file paths to the local cache. CkJsonObject_put_EmitCompact $jsonMaster 0 set strJsonMaster [CkJsonObject_emit $jsonMaster] CkCache_SaveTextNoExpire $gdCache "AllGoogleDriveFileIds" "" $strJsonMaster puts "JSON Master Record:" puts "$strJsonMaster" # The JSON Master Cache Record looks something like this: # An application can load the JSON master record and iterate over all the files # in Google Drive by file ID, or by path. # { # "fileIds": [ # "0B53Q6OSTWYolQlExSlBQT1phZXM", # "0B53Q6OSTWYolVHRPVkxtYWFtZkk", # "0B53Q6OSTWYolRGZEV3ZGUTZfNFk", # "0B53Q6OSTWYolS2FXSjliMXQxSU0", # "0B53Q6OSTWYolZUhxckMzb0dRMzg", # "0B53Q6OSTWYolbUF6WS1Gei1oalk", # "0B53Q6OSTWYola296ODZUSm5GYU0", # "0B53Q6OSTWYolbTE3c3J5RHBUcHM", # "0B53Q6OSTWYolTmhybWJSUGd5Q2c", # "0B53Q6OSTWYolY2tPU1BnYW02T2c", # "0B53Q6OSTWYolTTBBR2NvUE81Zzg", # ], # "filePaths": [ # "testFolder/abc/123/pigs.json", # "testFolder/starfish20.jpg", # "testFolder/penguins2.jpg", # "testFolder/starfish.jpg", # "testFolder/abc/123/starfish.jpg", # "testFolder/abc/123/penguins.jpg", # "testFolder/abc/123", # "testFolder/abc", # "testFolder/testHello.txt", # "testFolder", # "helloWorld.txt", # ] # } puts "Entire cache rebuilt..." delete_CkAuthGoogle $gAuth delete_CkRest $rest delete_CkCache $gdCache delete_CkDateTime $dtExpire delete_CkJsonObject $jsonMaster delete_CkJsonObject $json delete_CkHashtable $hashTable delete_CkStringBuilder $sbPathForFileId delete_CkStringArray $saFileInfo delete_CkStringBuilder $sbPath |
© 2000-2024 Chilkat Software, Inc. All Rights Reserved.