【问题标题】:How to upload folder on Google Cloud Storage using Python API如何使用 Python API 在 Google Cloud Storage 上上传文件夹
【发布时间】:2014-10-25 07:24:33
【问题描述】:

我已在Google Cloud Storage 上成功上传单个文本文件。但是当我尝试上传whole folder 时,它会授予权限denied error.

filename = "d:/foldername"   #here test1 is the folder.


Error:
Traceback (most recent call last):
  File "test1.py", line 142, in <module>
    upload()
  File "test1.py", line 106, in upload
    media = MediaFileUpload(filename, chunksize=CHUNKSIZE, resumable=True)
  File "D:\jatin\Project\GAE_django\GCS_test\oauth2client\util.py", line 132, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "D:\jatin\Project\GAE_django\GCS_test\apiclient\http.py", line 422, in __init__
    fd = open(self._filename, 'rb')
IOError: [Errno 13] Permission denied: 'd:/foldername'

【问题讨论】:

标签: python django google-app-engine


【解决方案1】:

该解决方案也可用于 Windows 系统。只需提供文件夹名称即可上传目标存储桶名称。此外,它可以处理文件夹中的任何级别的子目录。

import os
from google.cloud import storage
storage_client = storage.Client()
def upload_files(bucketName, folderName):
"""Upload files to GCP bucket."""
bucket = storage_client.get_bucket(bucketName)
for path, subdirs, files in os.walk(folderName):
    for name in files:
        path_local = os.path.join(path, name)
        blob_path = path_local.replace('\\','/')
        blob = bucket.blob(blob_path)
        blob.upload_from_filename(path_local)

【讨论】:

    【解决方案2】:

    没有递归函数的版本,它适用于“顶级文件”(与顶级答案不同):

    import glob
    import os 
    from google.cloud import storage
    
    GCS_CLIENT = storage.Client()
    def upload_from_directory(directory_path: str, dest_bucket_name: str, dest_blob_name: str):
        rel_paths = glob.glob(directory_path + '/**', recursive=True)
        bucket = GCS_CLIENT.get_bucket(dest_bucket_name)
        for local_file in rel_paths:
            remote_path = f'{dest_blob_name}/{"/".join(local_file.split(os.sep)[1:])}'
            if os.path.isfile(local_file):
                blob = bucket.blob(remote_path)
                blob.upload_from_filename(local_file)
    

    【讨论】:

    • 这个脚本对我有用,但我只需要修改:bucket = GCS_CLIENT.bucket(dest_bucket_name) 而不是 bucket = GCS_CLIENT.get_bucket(dest_bucket_name)
    【解决方案3】:

    这对我有用。将本地目录中的所有内容复制到谷歌云存储中的特定存储桶名称/完整路径(递归):

    import glob
    from google.cloud import storage
    
    def upload_local_directory_to_gcs(local_path, bucket, gcs_path):
        assert os.path.isdir(local_path)
        for local_file in glob.glob(local_path + '/**'):
            if not os.path.isfile(local_file):
               upload_local_directory_to_gcs(local_file, bucket, gcs_path + "/" + os.path.basename(local_file))
            else:
               remote_path = os.path.join(gcs_path, local_file[1 + len(local_path):])
               blob = bucket.blob(remote_path)
               blob.upload_from_filename(local_file)
    
    
    upload_local_directory_to_gcs(local_path, bucket, BUCKET_FOLDER_DIR)
    

    【讨论】:

    • 这不适用于第一级的文件,但适用于更深层次的所有文件。第一级文件将截断文件名中的第一个字符
    • 你可以使用glob.glob(local_path + "/**", recursive=True),然后if os.path.isfile(local_file): upload_file来简化它
    【解决方案4】:

    参考 - https://hackersandslackers.com/manage-files-in-google-cloud-storage-with-python/

    from os import listdir
    from os.path import isfile, join
    
    ...
    
    def upload_files(bucketName):
        """Upload files to GCP bucket."""
        files = [f for f in listdir(localFolder) if isfile(join(localFolder, f))]
        for file in files:
            localFile = localFolder + file
            blob = bucket.blob(bucketFolder + file)
            blob.upload_from_filename(localFile)
        return f'Uploaded {files} to "{bucketName}" bucket.'
    

    【讨论】:

      【解决方案5】:

      文件夹是包含对文件和目录的引用的编目结构。该库将不接受文件夹作为参数。

      据我了解,您的用例是上传到 GCS 并保留本地文件夹结构。为此,您可以使用 os python 模块并创建一个将路径作为参数的递归函数(例如 process_folder)。该逻辑可用于函数:

      1. 使用 os.listdir() 方法获取源路径中的对象列表(将返回文件和文件夹)。
      2. 遍历步骤 1 中的列表,通过 os.path.isdir() 方法将文件与文件夹分开。
      3. 迭代文件并使用调整后的路径上传它们(例如路径+“/”+文件名)。
      4. 遍历文件夹进行递归调用(例如 process_folder(path+folder_name))。

      有必要使用两条路径:

      1. 与 os 模块一起使用的真实系统路径(例如“/Users/User/.../upload_folder/folder_name”)。
      2. GCS 文件上传的虚拟路径(例如,“upload”+”/“ + folder_name + ”/“ + file_name)。

      不要忘记实现 [1] 中引用的指数退避来处理 500 个错误。您可以使用 [2] 中的 Drive SDK 示例作为参考。

      [1] - https://developers.google.com/storage/docs/json_api/v1/how-tos/upload#exp-backoff
      [2] - https://developers.google.com/drive/web/handle-errors

      【讨论】:

        【解决方案6】:

        我认为纯粹的filename = "D:\foldername" 没有足够的源代码信息。我也不确定这是否可能......通过网络界面,您也可以上传文件或创建文件夹,然后上传文件。

        您可以保存文件夹名称,然后创建它(我从未使用过 google-app-engine,但我想应该可以),然后将内容上传到新文件夹

        【讨论】:

          猜你喜欢
          • 2019-11-07
          • 1970-01-01
          • 2020-06-13
          • 2016-08-28
          • 1970-01-01
          • 2014-01-05
          • 2017-04-02
          • 1970-01-01
          • 2014-11-22
          相关资源
          最近更新 更多