Docker环境下Python调用Google Drive API上传文件遇UnknownFileType错误
问题:Docker容器内调用Google Drive API上传XLSX文件触发UnknownFileType错误
在Docker环境中调用Google Drive API上传文件时出现以下错误,相同代码在Windows本地运行完全正常:
Traceback (most recent call last): File "/app/apis/gtest.py", line 60, in <module> media = drive_service.files().create(body=file_metadata, media_body=file_path).execute() File "/usr/local/lib/python3.9/site-packages/googleapiclient/discovery.py", line 1143, in method raise UnknownFileType(media_filename) googleapiclient.errors.UnknownFileType: upload/2d0a3e62-f442-4b2f-a816-f00e03a6f4db/someexcelfile.xlsx
需求是根据文件MIME类型上传XLSX或JSONL文件,其中JSONL文件已通过设置application/octet-stream MIME类型并使用MediaFileUpload对象正常上传,但XLSX文件在Docker内触发上述错误。
参考代码如下:
import os from datetime import date from google.oauth2 import service_account from googleapiclient.discovery import build # Define the Google Drive folder ID folder_id = 'somegoogledrivefolderid' # Define the file name with the correct file extension file_path = 'upload/2d0a3e62-f442-4b2f-a816-f00e03a6f4db/someexcelfile.xlsx' file_name = os.path.basename(file_path) # Use the base name of the file path # Check if the file extension is 'jsonl' file_ext = os.path.splitext(file_path)[1] # Extract the file extension if file_ext == '.jsonl': print("The file is a jsonl file") # Add your code here to handle jsonl files else: print("The file is not a jsonl file") # Add your code here to handle non-jsonl files # Generate the folder name based on the current date current_date = date.today().strftime('%m/%d/%Y') folder_name = os.path.join(current_date, '').replace("\\", "") # Authenticate and create a Google Drive service credentials = service_account.Credentials.from_service_account_file('scripts/gs_credentials.json') drive_service = build('drive', 'v3', credentials=credentials) # List folders in the specified folder folder_query = f"'{folder_id}' in parents and mimeType = 'application/vnd.google-apps.folder'" response = drive_service.files().list(q=folder_query).execute() # Check if folder already exists existing_folder_id = None for folder in response.get('files', []): if folder['name'] == folder_name: existing_folder_id = folder['id'] break if existing_folder_id: print(f"Folder already exists with ID: {existing_folder_id}") folder_id = existing_folder_id else: # Create the folder folder_metadata = { 'name': folder_name, 'parents': [folder_id], 'mimeType': 'application/vnd.google-apps.folder' } folder = drive_service.files().create(body=folder_metadata, fields='id').execute() folder_id = folder.get('id') print(f"New folder created with ID: {folder_id}") # Upload the file to the generated folder file_metadata = { 'name': file_name, 'parents': [folder_id] } media = drive_service.files().create(body=file_metadata,media_mime_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", media_body=file_path).execute() print(f'Successfully saved the file: {media["name"]}')
请问如何让Docker容器内正确识别文件MIME类型,确保上传正常工作?
解决方案
问题根源是Docker镜像(通常基于Linux)默认缺少完整的MIME类型数据库,导致googleapiclient无法通过文件扩展名自动识别XLSX的MIME类型。Windows系统自带完整的MIME映射,因此本地运行无问题。
方式一:显式使用MediaFileUpload指定MIME类型
不要直接将文件路径传给media_body,而是创建MediaFileUpload对象并明确指定MIME类型,绕过自动识别逻辑。修改上传部分代码:
from googleapiclient.http import MediaFileUpload # 替换原上传代码段 media = MediaFileUpload( file_path, mimetype="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ) response = drive_service.files().create( body=file_metadata, media_body=media ).execute()
这种方式最可靠,不受容器环境配置影响,同时和你处理JSONL文件的逻辑保持统一。
方式二:在Docker镜像中安装MIME类型数据库
如果希望保留自动识别逻辑,可以在Dockerfile中添加命令安装对应依赖包:
- 基于Debian/Ubuntu的镜像:
RUN apt-get update && apt-get install -y shared-mime-info - 基于Alpine的镜像:
RUN apk add --no-cache shared-mime-info
安装完成后,googleapiclient就能通过系统工具识别XLSX的MIME类型。
建议优先使用方式一,代码可移植性更强,无需依赖容器环境配置。
内容的提问来源于stack exchange,提问作者PythonKiddieScripterX
相关产品推荐
相关产品推荐

