如何使用 Python API 在 Google Cloud Storage 上上传文件夹

Posted

技术标签:

【中文标题】如何使用 Python API 在 Google Cloud Storage 上上传文件夹【英文标题】:How to upload folder on Google Cloud Storage using Python API 【发布时间】: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'

【问题讨论】:

整个文件夹。?我想你需要检查developers.google.com/appengine/docs/python/blobstore/… 压缩文件夹并上传。 【参考方案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)。该逻辑可用于函数:

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

有必要使用两条路径:

    与 os 模块一起使用的真实系统路径(例如“/Users/User/.../upload_folder/folder_name”)。 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,但我想应该可以),然后将内容上传到新文件夹

【讨论】:

以上是关于如何使用 Python API 在 Google Cloud Storage 上上传文件夹的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 python 发送 REST API(Google Vision 的 API)请求?

如何使用 Python API 在 Google Cloud Storage 上上传文件夹

如何使用 Google Sheets API python 将下拉列表添加到 google sheet

在 Python 项目中设置 GOOGLE_APPLICATION_CREDENTIALS 以使用 Google API

如何使用Appengine和来自API的Python脚本流数据将数据流式传输到Google Cloud BigQuery?

如何使用 Python 启用 Google Assistant API 的新“阅读”功能?