You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Blob.rewrite()跨存储桶复制文件时GCF报NotFound错误

问题描述

使用Google Cloud Function(GCF)的Blob.rewrite()方法在Google Cloud Storage(GCS)存储桶间复制文件时,触发NotFound错误:

NotFound: 404 POST https://storage.googleapis.com/storage/v1/b/ca-app-corp-finance-dev-444/o/process%2Ffin_essbase%2Fdata%2Fincoming%2Fessbase%2Fkey.ppk/rewriteTo/b/gcf-v2-uploads-632430838198-us-east1/o/key.ppk?prettyPrint=false: No such object: ca-app-corp-finance-dev-444/process/fin_essbase/data/incoming/essbase/key.ppk

场景与代码

GCF配置为:源存储桶gcf-v2-uploads-632430838198-us-east1有新文件上传时触发函数,目标是将文件复制到目标存储桶ca-app-corp-finance-dev-444的process/fin_essbase/data/incoming/essbase/路径下,使用Blob.rewrite()实现。代码片段如下:

from google.cloud import storage

def transfer_file(data, context):
    source_bucket_name = "gcf-v2-uploads-632430838198-us-east1"
    destination_bucket_name = "ca-app-corp-finance-dev-444"
    target_path = "process/fin_essbase/data/incoming/essbase/"
    filename = "key.ppk"

    storage_client = storage.Client()
    source_bucket = storage_client.bucket(source_bucket_name)
    destination_bucket = storage_client.bucket(destination_bucket_name)

    source_blob = source_bucket.blob(filename)
    destination_blob = destination_bucket.blob(target_path + filename)

    # Check if the destination blob already exists
    if destination_blob.exists():
        print(f"Destination blob {destination_blob.name} already exists.")
    else:
        try:
            # Perform a rewrite operation to copy the content
            token = source_blob.rewrite(destination_blob)

            # Wait for the rewrite to complete
            token.result()

            # Delete the source blob
            source_blob.delete()

            print(f"File {filename} transferred successfully.")
        except Exception as e:
            print(f"An error occurred: {e}")

已确认源对象存在、存储桶与路径无误,服务账号拥有源桶读取、目标桶写入权限,但仍触发错误。

排查与解决建议
  • 确认rewrite操作的对象方向
    从错误URL可见,API请求尝试将目标桶的对象重写到源桶,与业务逻辑完全相反。检查代码中source_blob和destination_blob的初始化逻辑,确保source_bucket对应源存储桶、source_blob指向源桶中存在的对象;destination_bucket对应目标存储桶、destination_blob指向目标路径。

  • 替换硬编码文件名,使用触发事件传递的对象名
    代码硬编码了filename = "key.ppk",但GCF触发事件会通过data['name']传递实际上传的文件名。若上传文件不是key.ppk,source_blob会指向不存在的对象,间接导致rewrite逻辑异常。修改代码使用触发事件的文件名:

    filename = data['name']
    # 若需去掉源桶中的路径前缀,可添加处理:filename = os.path.basename(data['name'])
    
  • 补全目标存储桶的权限配置
    尽管服务账号有目标桶写入权限,但destination_blob.exists()需要storage.objects.get权限,rewrite操作还需目标桶的storage.objects.create和storage.objects.update权限。确认服务账号的IAM角色包含:

    • 源桶:roles/storage.objectViewer(或自定义包含storage.objects.get的权限)
    • 目标桶:roles/storage.objectCreator + roles/storage.objectViewer(或直接使用roles/storage.objectAdmin)
  • 检查存储桶区域与跨区域访问限制
    若源桶和目标桶处于不同区域,确认是否存在VPC限制、组织政策等阻碍跨区域资源访问的配置。可临时将测试文件放在同区域桶中,验证rewrite功能是否正常。

  • 更新Google Cloud Storage Python客户端库
    旧版本客户端库可能存在rewrite方法的参数逻辑或API调用问题。在Function的requirements.txt中指定最新版本:

    google-cloud-storage>=2.15.0
    
  • 添加源对象存在性前置检查
    在执行rewrite前,先确认源对象存在,避免因源对象不存在导致的间接错误:

    if not source_blob.exists():
        print(f"Source blob {source_blob.name} does not exist.")
        return
    

内容的提问来源于stack exchange,提问作者Someone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 21:00:08