1

我们有一个包含 20000 张图像的本地目录,需要转到 GCS。使用 R (and googleCloudStorageR),我们可以遍历每个图像并上传到 GCS,如下所示:

# setup
library(googleCloudStorageR)
gcs_auth(json_file = 'my/gcs/admin/creds.json')
all_png_images <- list.files('../path/to/local-images/directory')

# and loop
for(i in 1:length(all_png_images)) {
    googleCloudStorageR::gcs_upload(
      file = paste0(base_url, all_png_images[i]),
      bucket = 'my-bucket',
      name = paste0('images-folder/', all_png_images[i]),
      predefinedAcl = 'default'
    )
}

这完美地工作......但是,如果我可以简单地指向目录并一次上传所有内容会更好,而不是必须指向一个目录并循环遍历每个文件。我曾尝试使用该gcs_save_all功能,但没有成功:

googleCloudStorageR::gcs_save_all(
  directory = 'path-to-all-images',
  bucket = 'my-bucket'
)

抛出错误2020-10-01 16:23:47 -- File size detected as 377.1 Kb 2020-10-01 16:23:47> Request Status Code: 400 Error: API returned: Cannot insert legacy ACL for an object when uniform bucket-level access is enabled. Read more at https://cloud.google.com/storage/docs/uniform-bucket-level-access

我试图找出为什么gcs_save_all不起作用,或者是否有另一种方法可以在 R 中做到这一点。

4

2 回答 2

2

编辑:

我在 googleCloudStorageR 上打开了一个问题,他们已在 GitHub 上的最新版本中修复了该问题,因此更新到该版本将允许您执行此操作:

googleCloudStorageR::gcs_save_all(
  directory = 'path-to-all-images',
  bucket = 'my-bucket',
  predefinedAcl = "bucketLevel"
)

原答案:

GCS 有两种方式处理存储桶中对象的授权:ACL 和 IAM。为了简化并让用户只担心一种授权方案,桶可以启用“统一桶级访问”,从而阻止使用 ACL。据推测,您的存储桶上启用了此功能。

当您设置 时predefinedAcl = 'default',您指定 GCS 不应该对 ACL 执行任何特殊操作,这是上传到具有统一存储桶级别访问权限的存储桶时的正确设置。

它似乎gcs_save_all没有这样的参数,并且默认值似乎是预定义的 ACL“私有”,当启用统一存储桶级访问时,这不是一个有效的选择。

于 2020-10-02T03:13:30.437 回答
1

库中的函数需要更新以支持存储桶级别 ACL,现在您可以通过指定支持的“bucketLevel”ACL 将其功能复制到将要修复的内容gcs_upload

例如

gcs_save_all <- function(directory = getwd(),
                         bucket = gcs_get_global_bucket(),
                         pattern = ""){

  tmp <- tempfile(fileext = ".zip")
  on.exit(unlink(tmp))

  bucket <- as.bucket_name(bucket)

  the_files <- list.files(path = directory,
                          all.files = TRUE,
                          recursive = TRUE,
                          pattern = pattern)
  
  withCallingHandlers(
    zip::zip(tmp, files = the_files),
    deprecated = function(e) NULL)

  # modified to accept ACL on bucket
  gcs_upload(tmp, bucket = bucket, name = directory, predefinedAcl = "bucketLevel")

}
于 2020-10-02T07:01:52.850 回答