Google Drive API批量上传因Latin-1编码错误失败,但单独上传正常
Google Drive API批量上传因Latin-1编码错误失败,但单独上传正常
我之前也碰到过一模一样的问题!本质原因是Google Drive API的批量请求(Batch HTTP)默认使用Latin-1(ISO-8859-1)编码来序列化请求体,而单个文件创建请求默认采用UTF-8编码。当请求体里包含Latin-1无法编码的字符(比如文件名里的特殊符号、或者像\ufffd这种编码替换字符),批量请求就会触发编码错误,而单个请求因为用UTF-8所以能正常工作。
下面给你几个可行的解决方案,按推荐程度排序:
方案1:强制批量请求使用UTF-8编码(最推荐)
直接修改批量请求的Content-Type头部,显式指定UTF-8编码,这样整个batch的请求体都会用UTF-8序列化,彻底解决编码问题。
修改你的批量请求创建代码:
# 原代码 # batch_request = drive_service.new_batch_http_request() # 修改后的代码 batch_request = drive_service.new_batch_http_request() # 手动设置batch请求的Content-Type头部,指定UTF-8编码 batch_request._headers['Content-Type'] = 'multipart/mixed; charset=utf-8'
补充说明:
- 虽然
_headers是私有属性,但在当前的Google API Python客户端版本(v2.x)中是稳定可用的;如果担心私有属性的兼容性,也可以通过创建batch时传入回调的方式间接设置,但上面的写法最简单直接。 - 你之前对文件名的
encode('utf-8').decode('utf-8')处理是多余的,直接用os.path.basename(excel_file_path)即可,Python字符串本身就是Unicode编码的。
方案2:预处理文件名,移除/替换Latin-1不支持的字符
如果不想修改batch的默认编码,可以先把文件名里的问题字符(比如\ufffd)替换成Latin-1支持的字符,比如问号?:
for idx, (excel_file_path, _) in enumerate(file_pairs): raw_file_name = os.path.basename(excel_file_path) # 替换掉Latin-1无法编码的字符 sanitized_file_name = raw_file_name.replace('\ufffd', '?') file_metadata = { 'name': sanitized_file_name, 'mimeType': 'application/vnd.google-apps.spreadsheet' } # 后续代码不变...
这个方案适合临时应急,但如果文件名里有大量特殊字符,还是方案1更彻底。
方案3:补全文件ID收集逻辑(你的原代码遗漏的点)
顺便提一下,你原代码里的file_id_mapping始终是空的,因为没有在batch请求的回调里收集上传后的文件ID。可以通过添加回调函数来完善这部分功能,结合方案1的完整代码如下:
def true_batch_upload_excel_files(file_pairs: List[Tuple[str, str]]) -> Dict[str, str]: drive_service = get_drive_service() file_id_mapping = {} def batch_callback(request_id, response, exception): # 回调函数:处理每个批量请求的结果 if exception: print(f"文件上传失败: {exception}") else: # 关联原文件路径和上传后的Google Drive文件ID original_file_path = file_pairs[int(request_id)][0] file_id_mapping[original_file_path] = response['id'] batch_request = drive_service.new_batch_http_request(callback=batch_callback) # 强制batch使用UTF-8编码 batch_request._headers['Content-Type'] = 'multipart/mixed; charset=utf-8' for idx, (excel_file_path, _) in enumerate(file_pairs): file_metadata = { 'name': os.path.basename(excel_file_path), 'mimeType': 'application/vnd.google-apps.spreadsheet' } media = MediaFileUpload( excel_file_path, mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ) batch_request.add( drive_service.files().create( body=file_metadata, media_body=media, fields='id' ), request_id=str(idx) # 给每个请求加ID,方便回调里对应原文件 ) try: batch_request.execute() print("批量上传完成") except Exception as e: print(f"批量上传出错: {e}") return file_id_mapping
额外提示
- 那个
\ufffd字符通常是文件名编码错误导致的(比如系统用了错误的编码解析文件名),如果预处理文件名时发现大量这种字符,建议检查你的文件系统编码是否正确(Windows下通常是GBK/UTF-8,Mac/Linux是UTF-8)。
备注:内容来源于stack exchange,提问作者2_DataCrawlers_Nawaf __
相关产品推荐
相关产品推荐

