如何使用Google Calendar API为事件添加附件?Python代码问题求助
Google Calendar API 添加Drive附件失败(无报错)
我正在用Python开发Google API相关功能,过往相关问题的答案大多已过时。遵循官方文档指引时,发现文档代码无法适配最新版API——文档提到使用alternateLink字段,但Drive API v3中该字段已不存在,根据资料改用webViewLink字段后,事件能成功创建,但附件未添加,且无任何报错信息。
补充代码
上传文件至Drive
def upload_file(drive_service, file_path): file_name = file_path.split("/")[-1] file_metadata = { "name": file_name, "parents": ["id to a folder in drive"], "mimeType": "application/pdf", } try: logging.info(f"Uploading the file {file_name}") media = MediaFileUpload(file_path, resumable=True) file = ( drive_service.files() .create( body=file_metadata, media_body=media, fields="id, mimeType, webContentLink", ) .execute() ) logging.info("File uploaded.") return file except HttpError as e: logging.error(f"An error occurred while uploading the file to drive: {e}") return
该函数返回包含id, mimeType, webContentLink字段的字典。
创建事件主体
def create_event_dict(info_list, attachment = []): from utils import date start_date = date.change_date_format(info_list[0], info_list[1]) end_date = date.change_date_format(info_list[3], info_list[4]) if attachment: attachment[0]["fileUrl"] = attachment[0]["webContentLink"] attachment[0].pop("webContentLink") event = { "summary": f"{info_list[2]} -> {info_list[5]}", "location": info_list[6], "start": {"dateTime": start_date.isoformat(), "timeZone": "Europe/Madrid"}, "end": {"dateTime": end_date.isoformat(), "timeZone": "Europe/Madrid"}, "reminders": {"useDefault": True}, "attachment": attachment, } return event
提交事件
def post_event(service, event, calendar_id): event = ( service.events() .insert(calendarId=calendar_id, body=event, supportsAttachments=True) .execute() ) print(f"Event created: {event.get('htmlLink')}") return event
解决方案
问题出在四个关键细节上,逐一修正即可解决:
字段名错误:单数/复数混淆
Calendar API要求的附件字段是复数attachments,而非代码中的单数attachment。API会忽略不存在的字段,这是附件未添加但无报错的核心原因。附件缺少必填字段
Calendar API的附件对象必须包含fileUrl、title、mimeType三个字段,原代码未提供title,需要从Drive返回的文件信息中获取文件名补充。Drive文件权限不足
上传的Drive文件默认是私有权限,Calendar API无法访问。需要在文件上传后添加公开读取权限,或授予特定用户/服务账号访问权限。上传时未获取文件名
原upload_file函数的fields参数未包含name,无法获取文件名作为附件的title,需要修改该参数。
修正后的代码片段
修正上传文件函数(添加权限+返回文件名)
def upload_file(drive_service, file_path): file_name = file_path.split("/")[-1] file_metadata = { "name": file_name, "parents": ["id to a folder in drive"], "mimeType": "application/pdf", } try: logging.info(f"Uploading the file {file_name}") media = MediaFileUpload(file_path, resumable=True) file = ( drive_service.files() .create( body=file_metadata, media_body=media, fields="id, name, mimeType, webContentLink", # 添加name字段 ) .execute() ) # 给文件添加公开读取权限,确保Calendar能访问 permission = { "type": "anyone", "role": "reader" } drive_service.permissions().create(fileId=file["id"], body=permission).execute() logging.info("File uploaded and permission set.") return file except HttpError as e: logging.error(f"An error occurred while uploading the file to drive: {e}") return
修正创建事件主体函数(复数字段+完整附件参数)
def create_event_dict(info_list, attachment = []): from utils import date start_date = date.change_date_format(info_list[0], info_list[1]) end_date = date.change_date_format(info_list[3], info_list[4]) attachments = [] if attachment: # 构造符合Calendar API要求的附件对象 attachments.append({ "fileUrl": attachment[0]["webContentLink"], "title": attachment[0]["name"], "mimeType": attachment[0]["mimeType"] }) event = { "summary": f"{info_list[2]} -> {info_list[5]}", "location": info_list[6], "start": {"dateTime": start_date.isoformat(), "timeZone": "Europe/Madrid"}, "end": {"dateTime": end_date.isoformat(), "timeZone": "Europe/Madrid"}, "reminders": {"useDefault": True}, "attachments": attachments, # 改为复数字段 } return event
额外检查项
- 确保已启用Google Calendar API和Google Drive API
- OAuth2权限范围需包含
https://www.googleapis.com/auth/calendar和https://www.googleapis.com/auth/drive.file
内容的提问来源于stack exchange,提问作者Tamames
相关产品推荐
相关产品推荐

