google-drive-api - 即使配置了授权字段,Google 幻灯片也会返回“提供的图像格式不受支持”
问题描述
最接近的线程是
https://stackoverflow.com/questions/60160794/getting-the-provided-image-is-in-an-unsupported-format-error-when-trying-to-in
但我不想打开与世界其他地方共享它的图像。所以我用域配置
file_id = uploaded_file.get('id')
drive_service.permissions().create(fileId=file_id, body={
'type': 'domain',
'domain': 'mydomain.com', # this is the domain I use the gsuite user e.g. richard@mydomain.com to login
'role': 'reader'
}).execute()
幻灯片资源由
def build_request(http, *args, **kwargs):
import google_auth_httplib2
new_http = google_auth_httplib2.AuthorizedHttp(credentials=drive_creds)
auth_header = {
'Authorization': 'Bearer '+ drive_creds.token
}
headers = kwargs.get('headers', {})
if not headers:
kwargs['headers'] = auth_headers
else:
kwargs['headers'].update(auth_header)
http_req = googleapiclient.http.HttpRequest(new_http, *args, **kwargs)
return http_req
slides_service = build('slides', 'v1', credentials=slides_creds, requestBuilder=build_request)
执行时,我可以观察到 kwargs 被传递给 HttpRequest 并正确配置了授权字段,例如
{'headers': {'Authorization': 'Bearer <google drive token>', ... }
但是在执行过程中,创建图像功能(我确信我的创建图像功能正常工作,因为一旦我使用公共可访问图像,例如谷歌徽标,将图像发布到谷歌幻灯片页面就没有问题)总是返回状态代码 400 和消息'提供的图像格式不受支持”。我打开一个私人窗口并粘贴链接,看起来它仍然重定向了登录页面的请求。
我需要配置任何其他步骤才能完成这项工作?非常感谢您的帮助。
更新 1:
下面的代码用于创建相应的幻灯片并基于 google doc 驱动资源。
slides_scopes = ['https://www.googleapis.com/auth/drive',
'https://www.googleapis.com/auth/drive.file',
'https://www.googleapis.com/auth/drive.readonly',
'https://www.googleapis.com/auth/presentations',
'https://www.googleapis.com/auth/spreadsheets',
'https://www.googleapis.com/auth/spreadsheets.readonly']
drive_scopes = ['https://www.googleapis.com/auth/drive',
'https://www.googleapis.com/auth/drive.appdata',
'https://www.googleapis.com/auth/drive.file',
'https://www.googleapis.com/auth/drive.metadata',
'https://www.googleapis.com/auth/drive.metadata.readonly',
'https://www.googleapis.com/auth/drive.photos.readonly',
'https://www.googleapis.com/auth/drive.readonly']
def auth(token_file='token.pickle', credentials_json='cred.json',scopes=[]):
creds = None
if os.path.exists(token_file):
with open(token_file, 'rb') as token:
creds = pickle.load(token)
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)
with open(token_file, 'wb') as token:
pickle.dump(creds, token)
return creds
slides_creds = auth(token_file='slides_t.pickle', credentials_json='slides_t.json', scopes=slides_scopes)
drive_creds = auth(token_file='drive_t.pickle', credentials_json='drive_t.json', scopes=drive_scopes)
def build_request(http, *args, **kwargs):
import google_auth_httplib2
new_http = google_auth_httplib2.AuthorizedHttp(credentials=drive_creds)
auth_header = {
'Authorization': 'Bearer '+ drive_creds.token
}
headers = kwargs.get('headers', {})
if not headers:
kwargs['headers'] = auth_headers
else:
kwargs['headers'].update(auth_header)
http_req = googleapiclient.http.HttpRequest(new_http, *args, **kwargs)
return http_req
slides_service = build('slides', 'v1', credentials=slides_creds, requestBuilder=build_request)
drive_service = build('drive', 'v3', credentials=drive_creds)
更新 2:
切换到使用本地 http 服务器提供图像时(可通过 访问http://<intranet ip or localhost>:<port>/path/to/img.png
,google slide api 返回以下错误
"Invalid requests[0].createImage: There was a problem retrieving the image. The provided image should be publicly accessible, within size limit, and in supported formats."
这让我想知道也许谷歌幻灯片 API 不再允许使用特殊权限(例如域)访问 webContentLink。只允许公开访问url。
更新 3:
create_image 函数参数:
slide_object_id:g6f1c6c22f2_1_69
web_content_link: https://drive.google.com/a/ {{域名}}/uc?id={{image id}}&export=download
尺寸:{'高度':{'幅度':10800,'单位':'EMU'},'宽度':{'幅度':19800,'单位':'EMU'}}
变换:{'scaleY':171.9097,'scaleX':212.4558,'translateY':937125,'translateX':2347875,'unit':'EMU'}
创建图像功能
def create_image(slides_service=None, slide_object_id=None, web_content_link=None, size_height_magnitude=4000000, size_width_magnitude=4000000, transform_scale_x=1, transform_scale_y=1, transform_translate_x=100000, transform_translate_y=100000): requests = [] requests.append({ 'createImage': { 'url': web_content_link, 'elementProperties': { 'pageObjectId': slide_object_id, 'size': { 'height': { 'magnitude': size_height_magnitude, 'unit': 'EMU' }, 'width': { 'magnitude': size_width_magnitude, 'unit': 'EMU' } }, 'transform': { 'scaleX': transform_scale_x, 'scaleY': transform_scale_y, 'translateX': transform_translate_x, 'translateY': transform_translate_y, 'unit': 'EMU' } } } }) body = { 'requests': requests } response = slides_service.presentations() \ .batchUpdate(presentationId=presentation_id, body=body).execute() return response.get('replies')[0].get('createImage')
解决方案
问题:
只有具有可公开访问 URL 的图像才能添加到幻灯片中。与发出请求的帐户共享图像是不够的。正如您在官方文档中看到的:
如果您想向幻灯片添加私有或本地图像,您首先需要在可公开访问的 URL 上提供它们。
解决方法:
正如Tanaike 的回答中所解释的,您可以做的是:(1) 公开共享图像,(2) 使用可公开访问的 URL 将图像添加到幻灯片中,以及 (3) 删除在步骤 1 中创建的权限。这方式,图像仅在程序执行步骤 2 和 3 所需的短时间内公开访问。
参考文档中提供的另一个选项是:
将您的图片上传到Google Cloud Storage并使用15 分钟 TTL 的签名 URL 。上传的图片会在 15 分钟后自动删除。
参考:
推荐阅读
- react-redux - 无法访问组件中的 redux 状态
- java - 带有 lambda 的原子变量
- r - 根据组对值进行排序
- microsoft-dynamics - Dynamics Nav - 如何检测用户取消选择行
- excel - 使用 VBA 更新切片器(OLAP 数据馈送)
- javascript - 使用 jquery 添加 data-i18n 属性
- reactjs - 如何在 react-dropzone 中的提交按钮上调用 axios?
- flutter - 具有关键概念的 statfulWidget
- reactjs - 在模拟子组件的开玩笑测试中无法读取 null 的属性
- html - 如何更改 HTML 中与背景图片相关的文本颜色?