从Google Drive Python API获取创建日期以进行下载

Jim*_*mmy 2 python google-drive-api

我想创建一个Python脚本来备份Google云端硬盘文件,这很有趣/很有趣,但是我遇到了麻烦。我下面的脚本可以正常工作,但是它只是备份了本地驱动器上所有文件的最后修改日期和创建日期作为备份的日期,并且没有保留原始的创建日期/修改日期在Google云端硬盘上。

这是我的脚本:

from __future__ import print_function
import sys, httplib2, os, datetime, io
from time import gmtime, strftime
from apiclient import discovery
import oauth2client
from oauth2client import client
from oauth2client import tools
from datetime import date

#########################################################################
# Fixing OSX el capitan bug ->AttributeError: 'Module_six_moves_urllib_parse' object has no attribute 'urlencode'
os.environ["PYTHONPATH"] = "/Library/Python/2.7/site-packages"
#########################################################################

CLIENT_SECRET_FILE = 'client_secrets.json'
TOKEN_FILE="drive_api_token.json"
SCOPES = 'https://www.googleapis.com/auth/drive'
APPLICATION_NAME = 'Drive File API - Python'
OUTPUT_DIR=str(date.today())+"_drive_backup"

try:
    import argparse
    flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
    flags = None

def get_credentials():
    home_dir = os.path.expanduser('~')
    credential_dir = os.path.join(home_dir, '.credentials')
    if not os.path.exists(credential_dir):
        os.makedirs(credential_dir)
    credential_path = os.path.join(credential_dir, TOKEN_FILE)
    store = oauth2client.file.Storage(credential_path)
    credentials = store.get()
    if not credentials or credentials.invalid:
        flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
        flow.user_agent = APPLICATION_NAME
        if flags:
            credentials = tools.run_flow(flow, store, flags)
        else: # Needed only for compatibility with Python 2.6
            credentials = tools.run(flow, store)
        print('Storing credentials to ' + credential_path)
    return credentials

def prepDest():
    if not os.path.exists(OUTPUT_DIR):
        os.makedirs(OUTPUT_DIR)
        return True
    return False

def downloadFile(file_name, file_id, file_createdDate, mimeType, service):
    request = service.files().get_media(fileId=file_id)
    if "application/vnd.google-apps" in mimeType:
        if "document" in mimeType:
            request = service.files().export_media(fileId=file_id, mimeType='application/vnd.openxmlformats-officedocument.wordprocessingml.document')
            file_name = file_name + ".docx"
        else: 
            request = service.files().export_media(fileId=file_id, mimeType='application/pdf')
            file_name = file_name + ".pdf"
    print("Downloading -- " + file_name)
    response = request.execute()
    with open(os.path.join(OUTPUT_DIR, file_name), "wb") as wer:
        wer.write(response)

def listFiles(service):
    def getPage(pageTok):
        return service.files().list(q="mimeType != 'application/vnd.google-apps.folder'",
               pageSize=1000, pageToken=pageTok, fields="nextPageToken,files(id,name, createdDate, mimeType)").execute()
    pT = ''; files=[]
    while pT is not None:
        results = getPage(pT)
        pT = results.get('nextPageToken')
        files = files + results.get('files', [])
    return files

def main():
        credentials = get_credentials()
        http = credentials.authorize(httplib2.Http())
        service = discovery.build('drive', 'v3', http=http)
        for item in listFiles(service):
            downloadFile(item.get('name'), item.get('id'), item.get('createdDate'), item.get('mimeType'), service)

if __name__ == '__main__':
    main()
Run Code Online (Sandbox Code Playgroud)

要尝试获取创建的日期,您可以在我添加到的上述脚本中看到,该脚本createdDate看起来像是我可以从文件中获取的一些元数据:https : //developers.google.com/drive/v2/reference/files

但是我不知道我是否正确地获取了该元数据,如果是,我实际上是如何将其分配给下载的文件的。

编辑:真的很抱歉,但我没有指定操作系统-这是针对Mac的。

ton*_*y19 5

Filev2 createdDate在v3中重命名为createdTime

您链接File引用是针对v2的,但是您的代码将连接到v3服务。当我运行从v2 API 使用的代码时,发生了错误(是无效的元数据字段)。createdDatecreatedDate

我切换到了v3 File API,该API将创建时间列为createdTime,并且能够无错误地检索时间。

文件创建时间只能在Windows中更改

Linux / Unix不允许设置文件的创建时间,但是它允许修改文件的修改时间和访问时间os.utime()(此功能需要两次)。Drive API提供了访问时间createdTimemodifiedTime但没有提供任何访问时间(在那儿可能没有意义),尽管修改时间也可以为访问时间提供服务。

在Windows中,可以使用设置文件创建时间win32file.SetFileTime

时间转换

请注意,自epoch以来,传递给上述timestamp函数的时间以秒为单位。Drive API返回一个ISO 8601字符串,我们将其转换为秒:

dt = datetime.datetime.strptime(dateTime, "%Y-%m-%dT%H:%M:%S.%fZ")
secs = int(dt.strftime("%s"))
Run Code Online (Sandbox Code Playgroud)

修改项

  1. 替换的所有实例createdDatecreatedTime

  2. 在中listFiles() > getPage(),添加modifiedTime到元数据字段:

    def listFiles(service):
        def getPage(pageTok):
            return service.files().list(q="mimeType != 'application/vnd.google-apps.folder'",
                                        pageSize=1000, pageToken=pageTok, fields="nextPageToken,files(id,name, createdTime, modifiedTime, mimeType)").execute()
    
    Run Code Online (Sandbox Code Playgroud)
  3. main()for-loop中,传递modifiedTimedownloadFiles()

    downloadFile(item.get('name'), item.get('id'), item.get('createdTime'), item.get('modifiedTime'), item.get('mimeType'), service)
    
    Run Code Online (Sandbox Code Playgroud)
  4. 在中downloadFiles(),在之后添加modifiedTime到参数列表file_createdTime

  5. 添加以下功能来设置文件时间戳:

    def dateToSeconds(dateTime):
        return int(datetime.datetime.strptime(dateTime, "%Y-%m-%dT%H:%M:%S.%fZ").strftime("%s"))
    
    def setFileTimestamps(fname, createdTime, modifiedTime):
        ctime = dateToSeconds(createdTime)
        mtime = dateToSeconds(modifiedTime)
        setFileCreationTime(fname, ctime)
        setFileModificationTime(fname, mtime)
    
    def setFileModificationTime(fname, newtime):
        # Set access time to same value as modified time,
        # since Drive API doesn't provide access time
        os.utime(fname, (newtime, newtime))
    
    def setFileCreationTime(fname, newtime):
        """http://stackoverflow.com/a/4996407/6277151"""
        if os.name != 'nt':
            # file creation time can only be changed in Windows
            return
    
        import pywintypes, win32file, win32con
    
        wintime = pywintypes.Time(newtime)
        winfile = win32file.CreateFile(
            fname, win32con.GENERIC_WRITE,
            win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE | win32con.FILE_SHARE_DELETE,
            None, win32con.OPEN_EXISTING,
            win32con.FILE_ATTRIBUTE_NORMAL, None)
    
        win32file.SetFileTime(winfile, wintime, None, None)
    
        winfile.close()
    
    Run Code Online (Sandbox Code Playgroud)
  6. 在中downloadFiles()setFileTimestamps()在写入文件后立即调用(作为函数的最后一行):

    def downloadFile(file_name, file_id, file_createdTime, modifiedTime, mimeType, service):
        request = service.files().get_media(fileId=file_id)
        if "application/vnd.google-apps" in mimeType:
            if "document" in mimeType:
                request = service.files().export_media(fileId=file_id, mimeType='application/vnd.openxmlformats-officedocument.wordprocessingml.document')
                file_name = file_name + ".docx"
            else:
                request = service.files().export_media(fileId=file_id, mimeType='application/pdf')
                file_name = file_name + ".pdf"
        print("Downloading -- " + file_name)
        response = request.execute()
        prepDest()
        fname = os.path.join(OUTPUT_DIR, file_name)
        with open(fname, "wb") as wer:
            wer.write(response)
    
        setFileTimestamps(fname, file_createdTime, modifiedTime)
    
    Run Code Online (Sandbox Code Playgroud)

GitHub回购