You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Requests实现带进度条的Google Drive指定文件夹上传故障排查

修复Google Drive文件上传到指定文件夹的问题

我用Python Requests写了不依赖Google Drive官方SDK的文件上传代码,带进度条,但文件无法上传到指定文件夹,调整后仍未解决,求修复方案。

原代码

import os
import sys
import json
import requests
import collections
from tqdm import tqdm
import requests_toolbelt
from requests.exceptions import JSONDecodeError

class ProgressBar(tqdm):
    def update_to(self, n: int) -> None:
        self.update(n - self.n)

def upload_file(access_token:str, filename:str, filedirectory:str, folder_id: str):

    metadata = {
        "name": filename,
        "parents": [{"id": folder_id}]
    }

    session = requests.session()

    with open(filedirectory, "rb") as fp:
        files = collections.OrderedDict(data=("metadata", json.dumps(metadata), "application/json"), file=fp)
        encoder = requests_toolbelt.MultipartEncoder(files)
        with ProgressBar(
            total=encoder.len,
            unit="B",
            unit_scale=True,
            unit_divisor=1024,
            miniters=1,
            file=sys.stdout,
        ) as bar:
            monitor = requests_toolbelt.MultipartEncoderMonitor(
                encoder, lambda monitor: bar.update_to(monitor.bytes_read)
            )

            r = session.post(
                "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart",
                data=monitor,
                allow_redirects=False,
                json=metadata,
                headers={"Authorization": "Bearer " + access_token, "Content-Type": monitor.content_type},
            )

    try:
        resp = r.json()
        print(resp)
    except JSONDecodeError:
        sys.exit(r.text)

upload_file(access_token, filename, filedirectory, "12345asdfghj")

问题分析

  • 元数据格式错误:Google Drive API要求parents字段是文件夹ID的数组,而非包含id键的对象数组,正确格式应为[folder_id]。
  • 请求参数冲突:同时传递data=monitor(multipart格式数据)和json=metadata会导致请求内容混乱,multipart数据中已包含元信息,无需额外传递json参数。
  • Multipart字段命名问题:OrderedDict中的键名data不符合API要求,应直接使用metadata作为字段名,确保API能正确识别元数据部分。

修复后的代码

import os
import sys
import json
import requests
import collections
from tqdm import tqdm
import requests_toolbelt
from requests.exceptions import JSONDecodeError

class ProgressBar(tqdm):
    def update_to(self, n: int) -> None:
        self.update(n - self.n)

def upload_file(access_token: str, filename: str, filedirectory: str, folder_id: str):
    # 修正parents字段格式:直接传入文件夹ID数组
    metadata = {
        "name": filename,
        "parents": [folder_id]
    }

    session = requests.session()

    with open(filedirectory, "rb") as fp:
        # 修正Multipart字段命名,确保metadata字段被正确识别
        files = collections.OrderedDict([
            ("metadata", (None, json.dumps(metadata), "application/json")),
            ("file", (filename, fp, "application/octet-stream"))
        ])
        encoder = requests_toolbelt.MultipartEncoder(files)
        with ProgressBar(
            total=encoder.len,
            unit="B",
            unit_scale=True,
            unit_divisor=1024,
            miniters=1,
            file=sys.stdout,
        ) as bar:
            monitor = requests_toolbelt.MultipartEncoderMonitor(
                encoder, lambda monitor: bar.update_to(monitor.bytes_read)
            )

            # 移除冲突的json参数,仅保留multipart数据和正确的请求头
            r = session.post(
                "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart",
                data=monitor,
                allow_redirects=False,
                headers={
                    "Authorization": f"Bearer {access_token}",
                    "Content-Type": monitor.content_type
                },
            )

    try:
        resp = r.json()
        if r.status_code == 200:
            print(f"文件上传成功,文件ID:{resp['id']}")
        else:
            print(f"上传失败:{resp}")
    except JSONDecodeError:
        sys.exit(f"请求错误:{r.text}")

# 替换为实际的access_token、filename、文件路径和目标文件夹ID
upload_file("your_access_token", "example.txt", "/path/to/example.txt", "12345asdfghj")

补充说明

  • 确保你的access_token拥有https://www.googleapis.com/auth/drive的权限,否则无法修改文件的父文件夹。
  • 修复后的代码中,Multipart的metadata部分使用(None, json.dumps(metadata), "application/json"),其中None表示该部分没有文件名,符合API对元数据部分的要求。
  • 给file部分指定了文件名和正确的MIME类型,避免API识别文件类型出错。

内容的提问来源于stack exchange,提问作者jak bin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 07:22:57