【问题标题】:Get createdDate from Google Drive Python API for downloads从 Google Drive Python API 获取 createdDate 以供下载
【发布时间】:2017-04-05 22:58:29
【问题描述】:

我想创建一个 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()

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

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

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

【问题讨论】:

    标签: python google-drive-api


    【解决方案1】:

    File v2 createdDate 在 v3 中重命名为 createdTime

    File 引用 you linked 适用于 v2,但您的代码连接到 v3 服务。当我运行您使用 v2 API 中的 createdDate 的代码时,发生了错误(createdDate 是无效的元数据字段)。

    我切换到v3 File API,将创建时间列为createdTime,并且能够正确检索时间。

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

    Linux/Unix 不允许设置文件的创建时间,但允许通过os.utime() 修改文件的修改时间和访问时间(这两个时间都需要这个函数)。 Drive API 提供了createdTimemodifiedTime,但没有提供访问时间(这可能在那里没有意义),尽管修改时间也可以用于访问时间。

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

    时间换算

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

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

    修改

    1. 将所有createdDate 实例替换为createdTime

    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()
      
    3. main()for-loop 中,将modifiedTime 传递给downloadFiles()

      downloadFile(item.get('name'), item.get('id'), item.get('createdTime'), item.get('modifiedTime'), item.get('mimeType'), service)
      
    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()
      
    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)
      

    GitHub repo

    【讨论】:

    • 非常感谢您提供此代码,它似乎只是门票。我真的很抱歉,但我意识到我没有指定操作系统并且我在 Mac 上,但看起来你的代码提到了 windows。将其转换为 mac 是否可以快速移植?
    • @Jimmy 没问题。该代码适用于 Linux/Unix(包括 macOS)或 Windows。我添加了 Windows 实现以防您使用它,如果您不在 Windows 上,该功能将正常退出。请注意,无法在 macOS 中编辑文件创建时间。 (还要注意我自己在 Mac 上,这是我测试这段代码的地方)
    • 嗨托尼。我将把它标记为已解决,因为您已经投入了大量工作,而且它似乎确实下载了一些文件并保存了它们。问题是,无论出于何种原因,它只下载 9 个文件并从一个文件夹停止。我不太清楚为什么。我已经运行了几次,它似乎总是下载相同的 9 个文件并停止。你能想到什么原因吗?
    • 跟这个有关系吗?对于listFiles(service)[:10]:中的项目?
    • 啊,是的。在 GitHub 存储库中,我添加了 10 项限制以避免下载大量文件(我的 Google 云端硬盘已满)。我已经取消了限制。 github.com/tony19-sandbox/google-drive-file-timestamps/commit/…
    猜你喜欢
    • 2023-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-03
    • 2020-05-23
    • 1970-01-01
    • 2019-12-13
    • 1970-01-01
    相关资源
    最近更新 更多