Google 幻灯片 returns 'The provided image is in an unsupported format' 即使配置了授权字段
Google slides returns 'The provided image is in an unsupported format' even with Authorization fields configured
最近的线程是
但我不想打开与世界其他地方分享的图像。所以我配置域
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>', ... }
但是在执行期间,创建图像功能(我确定我的创建图像功能可以正常工作,因为一旦我使用 public 可访问图像,例如 google 徽标,将图像发布到google 幻灯片页)总是 returns 状态代码 400 和消息 'The provided image is in an unsupported format'。我打开一个私人 window 并粘贴 link,看起来它仍然被重定向到登录页面的请求。
我需要配置任何其他步骤才能完成这项工作吗?非常感谢您的帮助。
更新 1:
下面的代码用于根据google文档创建相应的幻灯片和驱动资源。
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 幻灯片 api returns 跟随错误
"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."
这让我想知道也许 google slide API 不再允许以特殊权限(例如域)访问 webContentLink。只允许 public 可访问 url。
更新 3:
create_image函数参数:
slide_object_id: g6f1c6c22f2_1_69
web_content_link: https://drive.google.com/a/{{域名}}/uc?id={{图片id}}&export=download
尺寸:{'height':{'magnitude':10800,'unit':'EMU'},'width':{'magnitude': 19800, 'unit': '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 的图像才能添加到幻灯片中。与发出请求的帐户共享图像是不够的。正如您在 the official documentation:
中看到的
If you want to add private or local images to a slide, you'll first need to make them available on a publicly accessible URL.
解决方法:
如 Tanaike's answer 中所述,您可以做的是:(1) 公开分享图像,(2) 使用可公开访问的 URL,并且(3)删除在步骤 1 中创建的权限。这样,图像仅在程序执行步骤 2 和 3 的短时间内可公开访问。
参考文档中提供的另一个选项是:
upload your images to Google Cloud Storage and use signed URLs with a 15 minute TTL. Uploaded images are automatically deleted after 15 minutes.
参考:
最近的线程是
但我不想打开与世界其他地方分享的图像。所以我配置域
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>', ... }
但是在执行期间,创建图像功能(我确定我的创建图像功能可以正常工作,因为一旦我使用 public 可访问图像,例如 google 徽标,将图像发布到google 幻灯片页)总是 returns 状态代码 400 和消息 'The provided image is in an unsupported format'。我打开一个私人 window 并粘贴 link,看起来它仍然被重定向到登录页面的请求。
我需要配置任何其他步骤才能完成这项工作吗?非常感谢您的帮助。
更新 1:
下面的代码用于根据google文档创建相应的幻灯片和驱动资源。
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 幻灯片 api returns 跟随错误
"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."
这让我想知道也许 google slide API 不再允许以特殊权限(例如域)访问 webContentLink。只允许 public 可访问 url。
更新 3:
create_image函数参数:
slide_object_id: g6f1c6c22f2_1_69
web_content_link: https://drive.google.com/a/{{域名}}/uc?id={{图片id}}&export=download
尺寸:{'height':{'magnitude':10800,'unit':'EMU'},'width':{'magnitude': 19800, 'unit': '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 的图像才能添加到幻灯片中。与发出请求的帐户共享图像是不够的。正如您在 the official documentation:
中看到的If you want to add private or local images to a slide, you'll first need to make them available on a publicly accessible URL.
解决方法:
如 Tanaike's answer 中所述,您可以做的是:(1) 公开分享图像,(2) 使用可公开访问的 URL,并且(3)删除在步骤 1 中创建的权限。这样,图像仅在程序执行步骤 2 和 3 的短时间内可公开访问。
参考文档中提供的另一个选项是:
upload your images to Google Cloud Storage and use signed URLs with a 15 minute TTL. Uploaded images are automatically deleted after 15 minutes.