Reputation: 1897
I am trying to insert an image (PNG) in a Google Slide presentation using the Slides API. I do this by first uploading the image to the user's Drive, obtaining the url, passing that along to the Slide API via the correct request and then deleting the image file.
What used to work as of a few weeks ago:
image_url = '%s&access_token=%s' % (
drive_service.files().get_media(fileId=image_file_id).uri,
creds.token)
However, there have been changes to the Drive API, such that URLS constructed this way no longer work.
I am having difficulty figuring out the new correct URL to use here. The options as per the doc that describes the change are:
I use code that looks like this to get these links:
upload = drive_service.files().create(
body={'name': 'My Image File'},
media_body=media_body,
fields='webContentLink, id, webViewLink').execute()
image_url = upload.get('webContentLink')
I have tried both #1 and #2 and get the following error:
"Invalid requests[0].createImage: The provided image is in an unsupported format."
I have also been receiving the following error intermittently:
"Invalid requests[0].createImage: Access to the provided image was forbidden."
I verified that I am able to download / view the image from the URLs generated in #1 and #2. I didn't try #3 since I am not trying to export to a different format.
What would be the best way to go about figuring out the correct URL to use?
Upvotes: 0
Views: 6300
Reputation: 23
I was running into the same error even when using the flow involving granting temporary permissions access then removing the permissions after calling .createImage()
or .replaceAllShapesWithImage()
I also ran into this error when creating permissions for a folder containing those images: "Invalid requests[0].replaceAllShapesWithImage: Access to the provided image was forbidden."
Not sure why the permissions are not propagating to the images...
Following Kos' comment, switching to jpg file type worked for me.
Edit:
It appears I am also required to set the scope to 'https://www.googleapis.com/auth/drive'
in order for it to work, which isn't ideal, but is sufficient for now.
Edit 2:
Nevermind it appears to be inconsistent. I am running into the permissions access error again. Deleting my token.pickle
does not seem to fix either
Upvotes: 0
Reputation: 201703
From your script, I think that the reason of your issue is due to this. By this, the query parameter of access_token
cannot be used. Under this situation, when image_url = '%s&access_token=%s' % (drive_service.files().get_media(fileId=image_file_id).uri,creds.token)
is used, the login page is returned. By this, such error occurs. So as a workaround, how about the following flow?
When the image file is put to the Slides, even when the permission of file is deleted, the image is not removed from the Slides. This workaround uses this.
For above flow, the sample script of python is as follows. Please set the variables of uploadFilename
, presentation_id
and pageObjectId
uploadFilename = './sample.png' # Please set the filename with the path.
presentation_id = '###' # Please set the Google Slides ID.
pageObjectId = '###' # Please set the page ID of the Slides.
drive = build('drive', 'v3', credentials=creds)
slides = build('slides', 'v1', credentials=creds)
# 1. Upload a PNG file from local PC
file_metadata = {'name': uploadFilename}
media = MediaFileUpload(uploadFilename, mimetype='image/png')
upload = drive.files().create(body=file_metadata, media_body=media, fields='webContentLink, id, webViewLink').execute()
fileId = upload.get('id')
url = upload.get('webContentLink')
# 2. Share publicly the uploaded PNG file by creating permissions.
drive.permissions().create(fileId=fileId, body={'type': 'anyone', 'role': 'reader'}).execute()
# 3. Insert the PNG file to the Slides.
body = {
"requests": [
{
"createImage": {
"url": url,
"elementProperties": {
"pageObjectId": pageObjectId
}
}
}
]
}
slides.presentations().batchUpdate(presentationId=presentation_id, body=body).execute()
# 4. Delete the permissions. By this, the shared PNG file is closed.
drive.permissions().delete(fileId=fileId, permissionId='anyoneWithLink').execute()
If I misunderstood your question and this was not the direction you want, I apologize.
Upvotes: 3