欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

如何使用 Python 从 Google Drive 下载文件(附代码示例)

最编程 2024-04-27 07:04:00
...

简介

Download files from Google Drive using Python

在这篇文章中,你将创建一个Python脚本来从Google Drive下载文件和上传文件。创建完脚本后,你可以将其与你的网络应用和API集成,以便从Google Drive下载文件和上传文件。

前提条件

在你开始这篇文章之前,你需要以下条件。

  • 一个可以运行python的环境
  • 一些关于Python脚本和简单的面向对象编程的知识
    注意:我在这个项目中使用python3.10.6 和Ubuntu操作系统。Python版本>=3.8版,对本文来说应该都是一样的。

第1步 - 环境设置

创建一个新的目录,并使用mkdir your_directory; cd your_directory

来改变它
对于这篇文章,我们需要创建并激活一个新的虚拟环境。

python3.10 -m venv your_virtual_environment # Create a virtual environment named .venv
. your_virtual_environment/bin/activate # activate the created virtual environment

然后,你将安装google-api-python-client, google-auth-httplib2, google-auth-oauthlib
使用pip install oogle-api-python-client google-auth-httplib2 google-auth-oauthlib 安装它们

第2步 - 谷歌API凭证

我们现在已经完成了要求,让我们从这个链接(谷歌云)获得我们的凭证。用你喜欢的账户登录,你应该有下面这个页面。Download files from Google Drive using Python

通过点击上面圈出的顶栏上的 "启用APIS和服务"来启用Google Drive API。你应该得到一个页面,你可以搜索要启用的API。搜索Google Drive ,然后点击它。之后,你将被引导到一个你可以启用它的页面。密切关注上述步骤,你应该看到以下结果。
Download files from Google Drive using Python

(搜索并点击谷歌API)

Download files from Google Drive using Python

(点击启用,你会得到上述结果)

现在导航回到[Google cloud](console.cloud.google.com/apis),然后点击左…

现在点击左侧边栏上的Credentials,然后点击顶部栏上的CREATE CREDENTIALS。按照下面显示的图片来设置你的凭证。
Download files from Google Drive using Python

点击OAuth客户端ID,如下图所示。
Download files from Google Drive using Python

然后在下拉菜单中点击网络应用作为应用类型,在应用名称字段中输入你的应用名称,并在其他输入字段中填写下图中规定的内容。
Download files from Google Drive using Python

你会得到一个弹出窗口,里面有你的凭证和一个下载按钮,可以下载credentials.json,点击它并下载它。
将credentials.json文件移到你的虚拟环境的目录中。

第3步 - 驱动器类

我们将创建一个Drive ,该类将有两个方法downloadupload 。下载将接受file_id和file_name作为参数,并根据我们请求的状态,返回True或False。如果我们成功下载,将返回True,否则将返回False。代码如下:

import io
import os
import pickle
import shutil
from mimetypes import MimeTypes

import requests
from google.auth.transport.requests import Request
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.http import MediaFileUpload, MediaIoBaseDownload


class Drive:
    SCOPES = ["https://www.googleapis.com/auth/drive"]

    def __init__(self):
        self.creds = None

        if os.path.exists("token.pickle"):
            with open("token.pickle", "rb") as token:
                self.creds = pickle.load(token)
        if not self.creds or not self.creds.valid:
            if self.creds and self.creds.expired and self.creds.refresh_token:
                self.creds.refresh(Request())
            else:
                flow = InstalledAppFlow.from_client_secrets_file(
                    "credentials.json", self.SCOPES
                )
                self.creds = flow.run_local_server(host="127.0.0.1", port=8000)
            with open("token.pickle", "wb") as token:
                pickle.dump(self.creds, token)
        self.service = build("drive", "v3", credentials=self.creds)
        results = (
            self.service.files()
            .list(
                pageSize=100,
                fields="files(id, name)",
            )
            .execute()
        )
        items = results.get("files", [])

        print("Here's a list of files: \n")
        print(*items, sep="\n", end="\n\n")

    def download(self, file_id, file_name):
        request = self.service.files().get_media(fileId=file_id)
        fh = io.BytesIO()

        downloader = MediaIoBaseDownload(fh, request, chunksize=204800)
        done = False

        try:
            while not done:
                status, done = downloader.next_chunk()

            fh.seek(0)

            with open(file_name, "wb") as f:
                shutil.copyfileobj(fh, f)

            print("File Downloaded")
            return True
        except:
            print("Something went wrong.")
            return False

    def upload(self, filepath):
        name = filepath.split("/")[-1]
        mimetype = MimeTypes().guess_type(name)[0]

        file_metadata = {"name": name}

        try:
            media = MediaFileUpload(filepath, mimetype=mimetype)

            file = (
                self.service.files()
                .create(body=file_metadata, media_body=media, fields="id")
                .execute()
            )

            print("File Uploaded.")

        except:
            raise UploadError("Can't Upload File.")

io 库用于处理各种类型的I/O (输入/输出)流,包括文本、二进制和原始IO。我们在这里需要的是从Google Drive中读取二进制io文件,如上面代码的第49行fh = io.BytesIO()
os ,用于处理文件,它被用在第20行。pickle 库在第22行用于反序列化(将json类型转换为python类型)。shutil 库与os 库相似,但它的功能更加高级。它在第61行被用来将一个文件的内容复制到另一个文件。而且我们导入了一些google-*库,以便与Drive API协同工作。每次我们运行脚本时都会创建一个token.pickle 文件,以便每次都能得到一个电子邮件选择提示。

第17-45行试图检查token.pickle文件是否存在,如果存在,其内容被分配到self.creds ,如果不存在,则创建一个新的,其内容被分配到self.creds 。该代码还检查凭证是否过期,如果过期,则生成一个新的。
该代码还列出了成功登录后的驱动器的内容(第34-45行)

所以我们可以从列出的文件中找到一个文件ID。

上传方法是将一个给定的文件路径上传到Google Drive,而下载方法是将一个给定的文件名称和ID从Google Drive下载。

下载方法

在第47行至第67行的下载方法中,我们使用self.service.files().get_media ,获得对googleapiclient 资源实例的引用,该实例返回一个字符串的媒体对象。

第54行到第70行downloader = MediaIoBaseDownload(fh, request, chunksize=204800) ,以输入流和对象的媒体资源为参数,以204800字节的分块方式下载媒体资源,同时可选择204800字节的分块大小,如果没有给出,则默认为1024*1024字节。我们在while循环中进行下载,同时处理错误,显示适当的错误信息并返回False。在while循环之后,我们使用shutil库中的shutil.copyfileobj(fh, f) ,将流写入文件。

上传方法

上传方法从第72行到第90行都有。在第73行和第74行中,我们从文件路径中获取文件名,因为我们知道文件名总是在路径中最后一个正斜线字符之后,访问-1 索引访问路径被分割后的最后一项/ 。而文件的MIME类型是通过MimeTypes 内建库获得的。
上传方法的主要功能依赖于googleapiclient库的MediaFileUpload 类。我们向它传递文件路径和MIME类型(media = MediaFileUpload(filepath, mimetype=mimetype) )。如果上传失败,我们从googleclient库中提出UploadError("Can't Upload File."))

第4步 - 主函数

主函数就像上面写的Drive API类的调用者。你应该把它放在你的脚本中的Drive类代码下面。它的主要作用是创建一个Drive 实例,从命令行接受输入1、2、3。把1作为命令行参数下载文件,2上传,而3退出代码。

def main():
    obj = Drive()
    try:
        action = int(os.sys.argv[1])
    except:
        help = f"USAGE: {os.sys.argv[0]} [1|2|3]\n1 - Download file, 2- Upload File, 3- Exit.\n"
        print(help)
        exit(0)

    if action == 1:
        f_id = input("Enter file id: ")
        f_name = input("Enter file name: ")
        obj.download(f_id, f_name)
    elif action == 2:
        f_path = input("Enter full file path: ")
        obj.upload(f_path)
    else:s
        try:
            os.remove("token.pickle")
        except:
            pass
        finally:
            exit()
    try:
        os.remove("token.pickle")
        exit(0)
    except:
        exit(1)
main()

下面是我的脚本的输入和输出。

python your_script.py 1 # downloading

Download files from Google Drive using Python
Download files from Google Drive using Python

python your_script.py 2 # uploading

Download files from Google Drive using Python

python your_script.py 3

Download files from Google Drive using Python

总结

在本教程中,我们已经创建了一个Google API类,来自Google云的credentials.json文件,并创建了一个脚本来下载和上传文件到Google Drive。我们还运行了代码并看到了输出。

推荐阅读