Search code examples
google-docs-api

Access to the provided image was forbidden even though it was uploaded from the same account


Using service account, I`m trying to create a folder in root folder available to the account and upload images to created folder.

async def create_folder(api, parent, name):
    return await api.as_service_account(
        drive.files.create(
            json = {
                'mimeType': 'application/vnd.google-apps.folder',
                'name': name,
                'parents': [parent]
            },
        )
    )

async def upload_file(api, path, parent, name):
    return await api.as_service_account(
        drive.files.create(
            upload_file = path,
            json = {
                'name': name,
                'parents': [parent]
            },
            fields = "id, name, webViewLink, webContentLink",
        )
    )

async def update_doc(api, id, requests):
    return await api.as_service_account(
        docs.documents.batchUpdate(
            documentId = id,
            json = {
                "requests": requests
            }
        )
    )

def insert_image(uri, index):
    return {
        "insertInlineImage": {
            "uri": uri,
            "location": {
                "index": index
            },
            "objectSize": {
                "height": {
                    "magnitude": 125,
                    "unit": "PT"
                },
            }
        }
    }

async def main(parent_id, path, file, doc_id):
    async with client.api: # my "wrapper" around Aiogoogle
        folder = await create_folder(
            client.api,
            parent_id,
            "A folder in root folder"
        )
        image = await upload_file(
            client.api,
            f"{path}/{file}",
            folder["id"],
            "A file in created folder",
        )
        await update_doc(
            client.api,
            doc_id,
            [insert_image(image["webContentLink"], 0)]
        )

And while both the file and the folder were in fact created (it even says the account is the owner of them), I`m getting this error:

{'code': 400,
 'message': 'Invalid requests[0].insertInlineImage: Access to the provided '
            'image was forbidden.',
 'status': 'INVALID_ARGUMENT'}

I tried giving these arguments to both of drive.files.create() calls:

includePermissionsForView = "published",
ignoreDefaultVisibility = True

, but no luck there


Solution

  • I think that when the image is put using webContentLink to Google Document using Docs API, the image is required to be publicly shared. So in your situation, how about the following patterns?

    Pattern 1:

    In this pattern, webContentLink is used. Please publicly share the uploaded file using the method of "Permissions: create" in Drive API. Ref

    By this, you can put the uploaded image using webContentLink. But in the current stage, there is the case that this link cannot be used. Ref I think that this might be a bug or the current specification.

    So, as a workaround, I would like to propose another pattern.

    Pattern 2:

    In this pattern, thumbnailLink is used instead of webContentLink by modifying the query parameter. In this case, it is not required to publicly share the uploaded file.

    Please add thumbnailLink to the fields like fields = "id, name, webViewLink, webContentLink, thumbnailLink", for drive.files.create. By this, thumbnailLink is included in the returned value. The value of thumbnailLink is as follows.

    https://lh3.googleusercontent.com/###=s220
    

    Please modify =s220 to =s1000. By this, the image size of the width of the image becomes large. Also, you can change this freely. And please use this modified URL to insertInlineImage.

    Reference: