Python存数据到Google Drive方法及redirect_uri_mismatch 400错误求助
准备工作
- 安装依赖库:
pip install google-api-python-client google-auth-httplib2 google-auth-oauthlib python-dotenv - 在Google Cloud控制台完成以下操作:
- 创建项目并启用Google Drive API
- 创建OAuth 2.0客户端ID,选择对应应用类型(本地开发选「桌面应用」,服务器选「Web应用」)
- 下载
credentials.json文件到项目根目录
实现代码
1. 认证与Drive客户端初始化
from google.auth.transport.requests import Request from google.oauth2.credentials import Credentials from google_auth_oauthlib.flow import InstalledAppFlow from googleapiclient.discovery import build from googleapiclient.errors import HttpError import os from dotenv import load_dotenv # 加载环境变量(可选,用于存储敏感信息) load_dotenv() # 定义权限:允许文件上传和读取 SCOPES = ["https://www.googleapis.com/auth/drive.file"] def get_drive_service(): creds = None # 检查是否有已保存的token.json if os.path.exists("token.json"): creds = Credentials.from_authorized_user_file("token.json", SCOPES) # 如果没有有效凭据,重新登录 if not creds or not creds.valid: if creds and creds.expired and creds.refresh_token: creds.refresh(Request()) else: flow = InstalledAppFlow.from_client_secrets_file( "credentials.json", SCOPES ) creds = flow.run_local_server(port=0) # 保存token供下次使用 with open("token.json", "w") as token: token.write(creds.to_json()) # 返回Drive服务实例 return build("drive", "v3", credentials=creds)
2. 上传媒体文件(图片/音频)
def upload_media_file(service, file_path, folder_id=None): try: file_metadata = { "name": os.path.basename(file_path) } # 指定上传到目标文件夹(可选) if folder_id: file_metadata["parents"] = [folder_id] media = service.files().create( body=file_metadata, media_body=file_path, fields="id" ).execute() print(f"文件上传成功,ID: {media.get('id')}") return media.get('id') except HttpError as error: print(f"上传失败:{error}") return None
3. 保存位置地址为文本文件并上传
def upload_location_data(service, location_info, file_name="location.txt", folder_id=None): # 将位置信息写入临时文本文件 temp_file = f"./{file_name}" with open(temp_file, "w", encoding="utf-8") as f: f.write(location_info) # 调用上传函数 file_id = upload_media_file(service, temp_file, folder_id) # 删除临时文件 os.remove(temp_file) return file_id
4. 主函数调用示例
if __name__ == "__main__": service = get_drive_service() # 上传图片 upload_media_file(service, "./captured_image.jpg") # 上传音频 upload_media_file(service, "./recorded_audio.mp3") # 上传位置地址(示例:"纬度: 39.9042, 经度: 116.4074, 地址: 北京市东城区") upload_location_data(service, "纬度: 39.9042, 经度: 116.4074, 地址: 北京市东城区")
以下是你可能遗漏的排查点及解决方案:
客户端类型不匹配:
如果是本地开发,必须创建「桌面应用」类型的OAuth客户端ID,而非「Web应用」。桌面应用的默认重定向URI为http://localhost或urn:ietf:wg:oauth:2.0:oob,若误用Web应用类型,即使URI一致也会触发错误。URI大小写敏感:
Google OAuth对重定向URI的大小写严格校验,比如http://localhost:8000与HTTP://LOCALHOST:8000会被判定为不同URI。确保代码与控制台设置的URI完全一致,包括大小写。修改后的URI未生效:
在Google Cloud控制台修改重定向URI后,需要等待5-10分钟才能生效,不要立即测试。实际请求的URI存在隐藏差异:
部分OAuth库会自动为URI添加额外参数或路径,可通过打印代码中的redirect_uri值,或抓包查看实际发送的请求URI,确认是否与控制台设置完全一致。重定向URI包含查询参数:
Google不允许重定向URI携带查询参数,比如http://localhost:8000/callback?user=test是无效的,必须移除所有查询参数,仅保留基础路径。多环境客户端ID混用:
如果项目下有多个客户端ID(本地、staging、生产),确认代码中加载的credentials.json是对应环境的文件,避免混用不同环境的客户端ID和URI。端口号不一致:
本地开发时,确保代码中使用的端口与控制台设置的重定向URI端口完全匹配,比如代码用8080,但控制台设的是8000,会直接触发错误。
内容的提问来源于stack exchange,提问作者dj jiiva

