【问题标题】:Google slides API replaceAllShapesWithImage returns error for Google Drive file (2020)Google 幻灯片 API replaceAllShapesWithImage 为 Google Drive 文件返回错误 (2020)
【发布时间】:2020-10-16 20:54:04
【问题描述】:

我正在尝试通过 API 将填充有占位符文本的 Google 幻灯片形状替换为图像。有问题的图像分配在团队驱动单元中。我已经阅读了几个解决方案,例如 thisthis,并尝试将图像中的权限设置为“reader”和“任何有链接的人” ,无论是通过 API 还是手动,都没有任何效果。我每次都收到“禁止访问所提供的图像”错误。但是,我可以通过 API 下载图像而不会出现问题,而无需提供额外的权限。 我正在使用 Drive API 的 v3 和 Slides API 的 v1。

下面是我正在使用的代码:

def replace_shape_with_image(slides_service, url, presentation_id, contains_text):
    requests = [
        {
            "replaceAllShapesWithImage": {
                "imageUrl": url,
                "replaceMethod": "CENTER_INSIDE",
                "containsText": {
                    "text": "{{" + contains_text + "}}",
                }
            }
        }]
    body = {
        'requests': requests
    }
        
    response = slides_service.presentations().batchUpdate(presentationId=presentation_id,body=body).execute()
    return response


def create_public_permissions(drive_service, file_id):
    request = drive_service.permissions().create(
        fileId=file_id,
        supportsAllDrives=True,
        fields='id, type, role',
        body={
            'role':'reader',
            'type':'anyone'
        }
    )
    response = request.execute()
    return response


file_id = '123'
presentation_id = '789'
# drive_service = etc
# slides_service = etc
create_public_permissions(drive_service, file_id) # Here I put the actual service object and file ID. Manually verified and it works
url = f'https://drive.google.com/uc?export=download&id={file_id}'
# also tried url = https://drive.google.com/uc?id={file_id}&export=download
replace_shape_with_image(slides_service, url, presentation_id, 'test') # shape in slide has "test" as text

返回如下错误:

googleapiclient.errors.HttpError:请求时 https://slides.googleapis.com/v1/presentations/1cDSov4IKFHSyzaXjFYNYPB7EYlMMtInamYv0AwXiazw:batchUpdate?alt=json 返回“无效请求[0].replaceAllShapesWithImage:访问 提供的图片被禁止。">

为了下载文件,我使用这个代码,没有问题:

import io
from googleapiclient.http import MediaIoBaseDownload


tmp_file_path = r'C:\Users\me\tmp\testimage.png'
fh = io.FileIO(tmp_file_path, 'wb')
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
    status, done = downloader.next_chunk()

我知道 Drive API 最近(过去一年)发生了变化,大多数关于此的问题都是旧的,解决方案已被弃用,最近的问题似乎对我不起作用。如果可能的话,关于如何解决这个问题的任何想法?

提前致谢!

【问题讨论】:

  • 我看到您正在使用两个服务(drive_service 和 slides_service) - 您如何验证这些服务?它们是启用了 Drive API 的同一个 GCP 项目的一部分吗?另外,您对每项服务的范围是什么?
  • 是的,它们是同一个项目的一部分。每个服务都有 service_account 模式。 Drive 应用程序具有“驱动器”范围,而幻灯片则具有“演示文稿”。两者都使用 OAUTH2。此配置由另一个人处理,因此我目前并不完全了解所有这些配置。
  • 明白了。您是在使用模拟还是作为服务帐户本身运行?
  • 它作为服务帐户本身运行
  • 很好奇,我似乎无法在我的环境中复制它。如果您不使用模拟,您如何修改您帐户上的云端硬盘文件的权限?另外,如果将https://www.googleapis.com/auth/drive.readonly 添加到slides_service 的范围内会发生什么?

标签: python google-drive-api google-slides-api


【解决方案1】:

已知问题:https://issuetracker.google.com/issues/150933939

正如我们的一个项目所发生的那样,我们发现在使用replaceAllShapesWithImage Slides API 请求时,并非所有 Google Drive 图像都会引发错误,而是随机图像。

唯一可能的解决方法是将您的请求代码包装在try / catch 中,并使用一些占位符图像以防replaceAllShapesWithImage 请求不断失败。

示例代码(在 Google Apps 脚本中):

var slideImageNotFoundPlaceholder = 'https://example.com/../placeholder.png';

try {
  Slides.Presentations.batchUpdate({'requests': slidesReqs}, presentationFileId);
}
catch(err)
{
    // loop all requests
    for (var i = 0; i < slidesReqs.length; i++)
    {
      // update replaceAllShapesWithImage requests
      if (slidesReqs[i].replaceAllShapesWithImage)
      {
        // replace with image not found placeholder
        slidesReqs[i].replaceAllShapesWithImage.imageUrl = slideImageNotFoundPlaceholder;
      }

    }

    Slides.Presentations.batchUpdate({'requests': slidesReqs}, presentationFileId);
}

这不是完美的解决方案,但所有其他请求都会得到执行,因此您的演示文稿不会完全失败。

附:希望 Google 能够修复在 Slides API 中使用的 Google Drive 图像,因此请在答案开头链接的问题上“加星标”以使其更快地发生。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-01
    相关资源
    最近更新 更多