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

15 投票
9 回答
21706 浏览
提问于 2025-04-19 03:54

我已经成功地把一个文本文件上传到 Google Cloud Storage。但是当我尝试上传 整个文件夹 时,系统却提示我权限 被拒绝

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'

9 个回答

0

参考链接 - 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.'
1

我想单单用 filename = "D:\foldername" 这段代码来描述源代码是不够的。我也不确定这样做是否真的可行。在网页界面上,你可以直接上传文件或者创建文件夹,然后再把文件放进去。

你可以先保存文件夹的名字,然后创建这个文件夹(我自己没用过谷歌应用引擎,但我猜应该是可以做到的),接着再把内容上传到新创建的文件夹里。

4

文件夹是一种用来整理文件和目录的结构。这个库不接受文件夹作为参数。

根据我的理解,你的需求是将本地的文件夹结构上传到GCS(谷歌云存储)。为了实现这个目标,你可以使用Python的os模块,写一个递归函数(比如叫process_folder),这个函数会把路径作为参数。下面是这个函数的逻辑:

  1. 使用os.listdir()方法获取源路径下的所有对象列表(会返回文件和文件夹)。
  2. 遍历第一步得到的列表,通过os.path.isdir()方法把文件和文件夹分开。
  3. 遍历文件并上传它们,路径要调整一下(比如:path + “/” + file_name)。
  4. 遍历文件夹,进行递归调用(比如:process_folder(path + folder_name))。

你需要处理两个路径:

  1. 真实的系统路径(例如:“/Users/User/…/upload_folder/folder_name”),这个路径是用os模块来处理的。
  2. 用于GCS文件上传的虚拟路径(例如:“upload” + “/” + folder_name + “/” + file_name)。

别忘了实现指数退避机制来处理500错误,参考文献[1]。你可以查看Drive SDK的示例作为参考[2]。

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

11

这是一个没有递归函数的版本,而且它可以处理“顶层文件”(和最受欢迎的答案不同):

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)
17

这个方法对我有效。它可以把本地目录里的所有内容复制到谷歌云存储中的一个特定的桶(bucket)和路径下,支持递归复制,也就是说可以把里面的文件夹和文件都一起复制过去:

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)

撰写回答