[我正在构建一个使用Google驱动器API的python应用程序,因此开发起来不错,但是我在检索整个Google驱动器文件树时遇到问题,出于两个目的,我需要使用它:
目前,我有一个获取Gdrive根目录的函数,我可以通过递归调用一个列出单个文件夹内容的函数来构建这三个目录,但是它非常慢,并且可能向Google和Google发出数千个请求这是不可接受的。
这里是获取根的函数:
def drive_get_root():
"""Retrieve a root list of File resources.
Returns:
List of dictionaries.
"""
#build the service, the driveHelper module will take care of authentication and credential storage
drive_service = build('drive', 'v2', driveHelper.buildHttp())
# the result will be a list
result = []
page_token = None
while True:
try:
param = {}
if page_token:
param['pageToken'] = page_token
files = drive_service.files().list(**param).execute()
#add the files in the list
result.extend(files['items'])
page_token = files.get('nextPageToken')
if not page_token:
break
except errors.HttpError, _error:
print 'An error occurred: %s' % _error
break
return result
这里是从文件夹中获取文件的人
def drive_files_in_folder(folder_id):
"""Print files belonging to a folder.
Args:
folder_id: ID of the folder to get files from.
"""
#build the service, the driveHelper module will take care of authentication and credential storage
drive_service = build('drive', 'v2', driveHelper.buildHttp())
# the result will be a list
result = []
#code from google, is working so I didn't touch it
page_token = None
while True:
try:
param = {}
if page_token:
param['pageToken'] = page_token
children = drive_service.children().list(folderId=folder_id, **param).execute()
for child in children.get('items', []):
result.append(drive_get_file(child['id']))
page_token = children.get('nextPageToken')
if not page_token:
break
except errors.HttpError, _error:
print 'An error occurred: %s' % _error
break
return result
例如,现在要检查文件是否存在,我正在使用此文件:
def drive_path_exist(file_path, list = False):
"""
This is a recursive function to che check if the given path exist
"""
#if the list param is empty set the list as the root of Gdrive
if list == False:
list = drive_get_root()
#split the string to get the first item and check if is in the root
file_path = string.split(file_path, "/")
#if there is only one element in the filepath we are at the actual filename
#so if is in this folder we can return it
if len(file_path) == 1:
exist = False
for elem in list:
if elem["title"] == file_path[0]:
#set exist = to the elem because the elem is a dictionary with all the file info
exist = elem
return exist
#if we are not at the last element we have to keep searching
else:
exist = False
for elem in list:
#check if the current item is in the folder
if elem["title"] == file_path[0]:
exist = True
folder_id = elem["id"]
#delete the first element and keep searching
file_path.pop(0)
if exist:
#recursive call, we have to rejoin the filpath as string an passing as list the list
#from the drive_file_exist function
return drive_path_exist("/".join(file_path), drive_files_in_folder(folder_id))
任何想法如何解决我的问题?我在这里看到了一些有关溢出的讨论,人们在一些回答中写道这是可能的,但是当然并没有说如何!
谢谢
停止将Drive视为树形结构。不是。 “文件夹”只是标签,例如。一个文件可以有多个父母。
为了在您的应用中构建树的表示,您需要执行此操作...
如果只想检查文件夹-B中是否存在文件-A,则方法取决于名称“文件夹-B”是否保证是唯一的。
如果是唯一的,只需对标题='file-A'进行FilesList查询,然后为其每个父项执行Files Get,并查看它们中的任何一个是否被称为'folder-B'。
如果“文件夹-B”可以同时存在于“文件夹-C”和“文件夹-D”下,则它会更加复杂,您将需要根据上述步骤1和步骤2构建内存中的层次结构。
您不说这些文件和文件夹是由您的应用还是由Google Drive Webapp的用户创建的。如果您的应用是这些文件/文件夹的创建者,那么可以使用一种技巧来将搜索限制在单个根目录下。说你有
MyDrive/app_root/folder-C/folder-B/file-A
您可以将app_root的所有文件夹-C,文件夹-B和文件-A设为子代>
这样,您可以约束所有查询以包括
and 'app_root_id' in parents
除了很小的树,永远不会那样工作。您必须重新考虑云应用程序的整个算法(您将其编写为拥有计算机的台式机应用程序一样),因为它很容易超时。您需要预先镜像树(任务队列和数据存储),不仅是为了避免超时,而且还要避免驱动速率限制,并以某种方式使其保持同步(注册推送等)。一点都不容易。我之前做过驱动器树查看器。
检查文件在特定路径中是否存在的简单方法是:drive_service.files()。list(q =“'THE_ID_OF_SPECIFIC_PATH'在父母和标题='一个文件'”).execute()
使用Google Drive Rest递归搜索文件https://stackoverflow.com/a/62372105/10435989