複製、重新命名及移動物件

本頁說明如何複製、重新命名及移動物件。部分工具會執行原子物件移動作業,其他工具則會將物件複製到指定的新位置,然後刪除原始物件,藉此模擬物件移動作業。

建議使用 Storage 移轉服務在值區之間移動超過 1 TB 的資料

事前準備

如要複製、重新命名或移動物件,您必須取得必要的 IAM 角色。以下各節說明不同用途的 IAM 需求。

複製物件 (包括透過複製移動或重新命名)

如要取得複製物件所需的權限,請要求管理員在來源值區 (內含要移動的物件) 或目標值區 (要將物件移至該處) 中,授予您下列 IAM 角色:

  • 來源 bucket 的 Storage 物件檢視者 (roles/storage.objectViewer)
  • 目標值區的 Storage 物件使用者 (roles/storage.objectUser)
  • 如要使用 Google Cloud 控制台複製物件,請在來源值區和目標值區中,除了 roles/storage.objectViewerroles/storage.objectUser 之外,還要有檢視者基本角色 (roles/viewer)。

這些預先定義的角色具備複製物件所需的權限。如要查看確切的必要權限,請展開「必要權限」部分:

所需權限

如要複製物件,必須具備下列權限:

  • storage.objects.get 來源 bucket
  • storage.objects.create 目的地 bucket
  • storage.objects.delete (只有在複製或移動物件時,需要取代或覆寫目的地 bucket 中的物件時,才需要這項權限) 目的地 bucket
  • storage.objects.delete (僅在您使用基礎複製和刪除作業移動物件時需要) 來源 bucket
  • storage.folders.create (只有在要移動的物件位於您要在目的地 bucket 中建立的資料夾時,才需要此參數) 目的地 bucket
  • storage.objects.list (僅在您使用 Google Cloud 控制台複製、移動或重新命名物件時需要) 來源和目標值區
  • storage.buckets.list (僅在使用 Google Cloud 控制台複製、移動或重新命名物件時需要)包含來源和目的地值區的專案

您也可以透過自訂角色取得這些權限。

如要瞭解如何授予值區角色,請參閱「搭配值區使用 IAM」。如要瞭解如何授予專案角色,請參閱「管理專案存取權」。

如果想複製的物件已啟用特定功能,您可能需要額外或替代角色。舉例來說,如果想複製的物件具有要保留的物件保留設定,您需要在目標值區中具備包含 storage.objects.setRetention 權限的角色,例如 Storage 物件管理員 (roles/storage.objectAdmin) 角色。詳情請參閱「Cloud Storage 的 IAM 權限」。

以原子方式重新命名物件

如要取得以原子方式重新命名物件所需的權限,請要求管理員授予您 bucket 的「Storage 物件使用者」 (roles/storage.objectUser) 身分與存取權管理角色。該 bucket 必須包含您要重新命名的物件。

這個預先定義的角色具備以原子方式重新命名物件所需的權限。如要查看確切的必要權限,請展開「必要權限」部分:

所需權限

如要以原子方式重新命名物件,您必須具備下列權限:

  • storage.objects.move
  • storage.objects.create
  • storage.objects.delete (只有在覆寫或取代物件時才需要)

您也可以透過自訂角色取得這些權限。

如要瞭解如何授予值區角色,請參閱「搭配值區使用 IAM」。

複製物件

本節說明如何複製物件。您可以將物件從一個值區複製到另一個值區。

控制台

  1. 在 Google Cloud 控制台,前往「Cloud Storage bucket」頁面。

    前往「Buckets」(值區) 頁面

  2. 在值區清單中,點選包含要複製物件的值區名稱。

    系統會開啟「Bucket details」(值區詳細資料) 頁面,並選取「Objects」(物件) 分頁標籤。

  3. 前往物件 (可能位於資料夾中)。

  4. 按一下與物件相關的「物件溢位」選單 ()。

  5. 按一下「複製」

    系統會顯示「複製物件」窗格。

  6. 在「Destination」(目的地) 欄位中,輸入目的地 bucket 的名稱和複製物件的名稱。

    您也可以按一下「瀏覽」選取目的地,但瀏覽選項僅限於目前專案中的值區。

  7. 按一下「複製」

如要瞭解如何透過 Google Cloud 控制台取得 Cloud Storage 作業失敗的詳細錯誤資訊,請參閱「疑難排解」一文。

指令列

使用 gcloud storage cp 指令:

gcloud storage cp gs://SOURCE_BUCKET_NAME/SOURCE_OBJECT_NAME gs://DESTINATION_BUCKET_NAME/NAME_OF_COPY

其中:

  • SOURCE_BUCKET_NAME 是包含要複製物件的值區名稱。例如:my-bucket
  • SOURCE_OBJECT_NAME 是要複製的物件名稱。例如:pets/dog.png
  • DESTINATION_BUCKET_NAME 是要將物件複製到的值區名稱。例如:another-bucket
  • NAME_OF_COPY 是您要給予複製物件的名稱。例如:shiba.png

如果成功,回應會類似以下範例:

Copying gs://example-bucket/file.txt to gs://other-bucket/file-copy.txt
  Completed files 1/1 | 164.3kiB/164.3kiB 

用戶端程式庫

C++

詳情請參閱 Cloud Storage C++ API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

namespace gcs = ::google::cloud::storage;
using ::google::cloud::StatusOr;
[](gcs::Client client, std::string const& source_bucket_name,
   std::string const& source_object_name,
   std::string const& destination_bucket_name,
   std::string const& destination_object_name) {
  StatusOr<gcs::ObjectMetadata> new_copy_meta =
      client.CopyObject(source_bucket_name, source_object_name,
                        destination_bucket_name, destination_object_name);
  if (!new_copy_meta) throw std::move(new_copy_meta).status();

  std::cout << "Successfully copied " << source_object_name << " in bucket "
            << source_bucket_name << " to bucket " << new_copy_meta->bucket()
            << " with name " << new_copy_meta->name()
            << ".\nThe full metadata after the copy is: " << *new_copy_meta
            << "\n";
}

C#

詳情請參閱 Cloud Storage C# API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。


using Google.Cloud.Storage.V1;
using System;

public class CopyFileSample
{
    public void CopyFile(
        string sourceBucketName = "source-bucket-name",
        string sourceObjectName = "source-file",
        string destBucketName = "destination-bucket-name",
        string destObjectName = "destination-file-name")
    {
        var storage = StorageClient.Create();
        storage.CopyObject(sourceBucketName, sourceObjectName, destBucketName, destObjectName);

        Console.WriteLine($"Copied {sourceBucketName}/{sourceObjectName} to " + $"{destBucketName}/{destObjectName}.");
    }
}

Go

詳情請參閱 Cloud Storage Go API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

import (
	"context"
	"fmt"
	"io"
	"time"

	"cloud.google.com/go/storage"
)

// copyFile copies an object into specified bucket.
func copyFile(w io.Writer, dstBucket, srcBucket, srcObject string) error {
	// dstBucket := "bucket-1"
	// srcBucket := "bucket-2"
	// srcObject := "object"
	ctx := context.Background()
	client, err := storage.NewClient(ctx)
	if err != nil {
		return fmt.Errorf("storage.NewClient: %w", err)
	}
	defer client.Close()

	ctx, cancel := context.WithTimeout(ctx, time.Second*10)
	defer cancel()

	dstObject := srcObject + "-copy"
	src := client.Bucket(srcBucket).Object(srcObject)
	dst := client.Bucket(dstBucket).Object(dstObject)

	// Optional: set a generation-match precondition to avoid potential race
	// conditions and data corruptions. The request to copy is aborted if the
	// object's generation number does not match your precondition.
	// For a dst object that does not yet exist, set the DoesNotExist precondition.
	dst = dst.If(storage.Conditions{DoesNotExist: true})
	// If the destination object already exists in your bucket, set instead a
	// generation-match precondition using its generation number.
	// attrs, err := dst.Attrs(ctx)
	// if err != nil {
	// 	return fmt.Errorf("object.Attrs: %w", err)
	// }
	// dst = dst.If(storage.Conditions{GenerationMatch: attrs.Generation})

	if _, err := dst.CopierFrom(src).Run(ctx); err != nil {
		return fmt.Errorf("Object(%q).CopierFrom(%q).Run: %w", dstObject, srcObject, err)
	}
	fmt.Fprintf(w, "Blob %v in bucket %v copied to blob %v in bucket %v.\n", srcObject, srcBucket, dstObject, dstBucket)
	return nil
}

Java

詳情請參閱 Cloud Storage Java API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。


import com.google.cloud.storage.BlobId;
import com.google.cloud.storage.BlobInfo;
import com.google.cloud.storage.CopyWriter;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.Storage.CopyRequest;
import com.google.cloud.storage.StorageOptions;

public class CopyObject {
  public static void copyObject(
      String projectId, String sourceBucketName, String objectName, String targetBucketName)
      throws Exception {
    // The ID of your GCP project
    // String projectId = "your-project-id";

    // The ID of the bucket the original object is in
    // String sourceBucketName = "your-source-bucket";

    // The ID of the GCS object to copy
    // String objectName = "your-object-name";

    // The ID of the bucket to copy the object to
    // String targetBucketName = "target-object-bucket";

    try (Storage storage =
        StorageOptions.newBuilder().setProjectId(projectId).build().getService()) {
      BlobId sourceId = BlobId.of(sourceBucketName, objectName);
      // you could change "objectName" to rename the object
      BlobId targetId = BlobId.of(targetBucketName, objectName);

      // Recommended: set a generation-match precondition to avoid potential race
      // conditions and data corruptions. The request returns a 412 error if the
      // preconditions are not met.
      Storage.BlobTargetOption precondition;
      BlobInfo existingTarget = storage.get(targetBucketName, objectName);
      if (existingTarget == null) {
        // For a target object that does not yet exist, set the DoesNotExist precondition.
        // This will cause the request to fail if the object is created before the request runs.
        precondition = Storage.BlobTargetOption.doesNotExist();
      } else {
        // If the destination already exists in your bucket, instead set a generation-match
        // precondition. This will cause the request to fail if the existing object's generation
        // changes before the request runs.
        precondition = Storage.BlobTargetOption.generationMatch(existingTarget.getGeneration());
      }

      CopyRequest copyRequest =
          CopyRequest.newBuilder()
              .setSource(sourceId)
              .setTarget(targetId, precondition)
              // limit the number of bytes Cloud Storage will attempt to copy before responding to
              // an individual request.
              // If you see Read Timeout errors, try reducing this value.
              .setMegabytesCopiedPerChunk(2048L) // 2GiB
              .build();
      CopyWriter copyWriter = storage.copy(copyRequest);
      BlobInfo successfulCopyResult = copyWriter.getResult();

      System.out.printf(
          "Copied object gs://%s/%s to %s%n",
          sourceBucketName,
          objectName,
          successfulCopyResult.getBlobId().toGsUtilUriWithGeneration());
    }
  }
}

Node.js

詳情請參閱 Cloud Storage Node.js API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// The ID of the bucket the original file is in
// const srcBucketName = 'your-source-bucket';

// The ID of the GCS file to copy
// const srcFilename = 'your-file-name';

// The ID of the bucket to copy the file to
// const destBucketName = 'target-file-bucket';

// The ID of the GCS file to create
// const destFileName = 'target-file-name';

// Imports the Google Cloud client library
const {Storage} = require('@google-cloud/storage');

// Creates a client
const storage = new Storage();

async function copyFile() {
  const copyDestination = storage.bucket(destBucketName).file(destFileName);

  // Optional:
  // Set a generation-match precondition to avoid potential race conditions
  // and data corruptions. The request to copy is aborted if the object's
  // generation number does not match your precondition. For a destination
  // object that does not yet exist, set the ifGenerationMatch precondition to 0
  // If the destination object already exists in your bucket, set instead a
  // generation-match precondition using its generation number.
  const copyOptions = {
    preconditionOpts: {
      ifGenerationMatch: destinationGenerationMatchPrecondition,
    },
  };

  // Copies the file to the other bucket
  await storage
    .bucket(srcBucketName)
    .file(srcFilename)
    .copy(copyDestination, copyOptions);

  console.log(
    `gs://${srcBucketName}/${srcFilename} copied to gs://${destBucketName}/${destFileName}`
  );
}

copyFile().catch(console.error);

PHP

詳情請參閱 Cloud Storage PHP API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

use Google\Cloud\Storage\StorageClient;

/**
 * Copy an object to a new name and/or bucket.
 *
 * @param string $bucketName The name of your Cloud Storage bucket.
 *        (e.g. 'my-bucket')
 * @param string $objectName The name of your Cloud Storage object.
 *        (e.g. 'my-object')
 * @param string $newBucketName The destination bucket name.
 *        (e.g. 'my-other-bucket')
 * @param string $newObjectName The destination object name.
 *        (e.g. 'my-other-object')
 */
function copy_object(string $bucketName, string $objectName, string $newBucketName, string $newObjectName): void
{
    $storage = new StorageClient();
    $bucket = $storage->bucket($bucketName);
    $object = $bucket->object($objectName);
    $object->copy($newBucketName, ['name' => $newObjectName]);
    printf('Copied gs://%s/%s to gs://%s/%s' . PHP_EOL,
        $bucketName, $objectName, $newBucketName, $newObjectName);
}

Python

詳情請參閱 Cloud Storage Python API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

from google.cloud import storage


def copy_blob(
    bucket_name, blob_name, destination_bucket_name, destination_blob_name,
):
    """Copies a blob from one bucket to another with a new name."""
    # bucket_name = "your-bucket-name"
    # blob_name = "your-object-name"
    # destination_bucket_name = "destination-bucket-name"
    # destination_blob_name = "destination-object-name"

    storage_client = storage.Client()

    source_bucket = storage_client.bucket(bucket_name)
    source_blob = source_bucket.blob(blob_name)
    destination_bucket = storage_client.bucket(destination_bucket_name)

    # Optional: set a generation-match precondition to avoid potential race conditions
    # and data corruptions. The request to copy is aborted if the object's
    # generation number does not match your precondition. For a destination
    # object that does not yet exist, set the if_generation_match precondition to 0.
    # If the destination object already exists in your bucket, set instead a
    # generation-match precondition using its generation number.
    # There is also an `if_source_generation_match` parameter, which is not used in this example.
    destination_generation_match_precondition = 0

    blob_copy = source_bucket.copy_blob(
        source_blob, destination_bucket, destination_blob_name, if_generation_match=destination_generation_match_precondition,
    )

    print(
        "Blob {} in bucket {} copied to blob {} in bucket {}.".format(
            source_blob.name,
            source_bucket.name,
            blob_copy.name,
            destination_bucket.name,
        )
    )

Ruby

詳情請參閱 Cloud Storage Ruby API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

def copy_file source_bucket_name:, source_file_name:, destination_bucket_name:, destination_file_name:
  # The ID of the bucket the original object is in
  # source_bucket_name = "source-bucket-name"

  # The ID of the GCS object to copy
  # source_file_name = "source-file-name"

  # The ID of the bucket to copy the object to
  # destination_bucket_name = "destination-bucket-name"

  # The ID of the new GCS object
  # destination_file_name = "destination-file-name"

  require "google/cloud/storage"

  storage = Google::Cloud::Storage.new
  bucket  = storage.bucket source_bucket_name, skip_lookup: true
  file    = bucket.file source_file_name

  destination_bucket = storage.bucket destination_bucket_name
  destination_file   = file.copy destination_bucket.name, destination_file_name

  puts "#{file.name} in #{bucket.name} copied to " \
       "#{destination_file.name} in #{destination_bucket.name}"
end

REST API

JSON API

  1. 安裝並初始化 gcloud CLI,以便為 Authorization 標頭產生存取權杖。

  2. 使用 cURL 透過 POST 物件要求呼叫 JSON API

    curl -X POST \
      -H "Authorization: Bearer $(gcloud auth print-access-token)" \
      -H "Content-Length: 0" \
      "https://storage.googleapis.com/storage/v1/b/SOURCE_BUCKET_NAME/o/SOURCE_OBJECT_NAME/rewriteTo/b/DESTINATION_BUCKET_NAME/o/NAME_OF_COPY"

    其中:

    • SOURCE_BUCKET_NAME 是包含要複製物件的值區名稱。例如:my-bucket
    • SOURCE_OBJECT_NAME 是要複製的物件名稱 (經過網址編碼)。例如 pets/dog.png,網址編碼為 pets%2Fdog.png
    • DESTINATION_BUCKET_NAME 是要將物件複製到的值區名稱。例如:another-bucket
    • NAME_OF_COPY 是您要給予複製物件的網址編碼名稱。例如:shiba.png

    由於 rewrite 方法會複製大小受限的區塊中的資料,因此複製作業可能需要多個要求,尤其是大型物件。

    舉例來說,下列 rewrite 要求的回應指出您需要發出額外的 rewrite 要求:

    {
      "kind": "storage#rewriteResponse",
      "totalBytesRewritten": 1048576,
      "objectSize": 10000000000,
      "done": false,
      "rewriteToken": TOKEN_VALUE
    }
  3. 在後續要求中使用 rewriteToken 以繼續複製資料:

    curl -X POST \
     -H "Authorization: Bearer $(gcloud auth print-access-token)" \
     -H "Content-Length: 0" \
     -d '{"rewriteToken": "TOKEN_VALUE"}' \
     "https://storage.googleapis.com/storage/v1/b/SOURCE_BUCKET_NAME/o/SOURCE_OBJECT_NAME/rewriteTo/b/DESTINATION_BUCKET_NAME/o/NAME_OF_COPY"

    其中:

    • TOKEN_VALUE 是上一個要求傳回的 rewriteToken 值。
    • 所有其他值都與先前要求中使用的值相符。

    物件完全複製完畢後,最後一個回應會有一個設為 truedone 屬性,沒有 rewriteToken 屬性,並且副本的中繼資料也包含在 resource 屬性中。

    {
     "kind": "storage#rewriteResponse",
     "totalBytesRewritten": 10000000000,
     "objectSize": 10000000000,
     "done": true,
     "resource": objects Resource
    }

XML API

  1. 安裝並初始化 gcloud CLI,以便為 Authorization 標頭產生存取權杖。

  2. 使用 cURL 透過 PUT 物件要求呼叫 XML API

    curl -X PUT \
      -H "Authorization: Bearer $(gcloud auth print-access-token)" \
      -H "x-goog-copy-source: SOURCE_BUCKET_NAME/SOURCE_OBJECT_NAME" \
      "https://storage.googleapis.com/DESTINATION_BUCKET_NAME/NAME_OF_COPY"

    其中:

    • SOURCE_BUCKET_NAME 是包含要複製物件的值區名稱。例如:my-bucket
    • SOURCE_OBJECT_NAME 是要複製的物件名稱。例如:pets/dog.png
    • DESTINATION_BUCKET_NAME 是要將物件複製到的值區名稱。例如:another-bucket
    • NAME_OF_COPY 是您要給予複製物件的網址編碼名稱。例如:shiba.png

透過複製移動或重新命名物件

本節說明如何使用基礎物件複製作業移動或重新命名物件。本節所述工具會將原始物件複製到其他命名空間,然後刪除原始物件,藉此執行物件移動和重新命名作業。

控制台

  1. 在 Google Cloud 控制台,前往「Cloud Storage bucket」頁面。

    前往「Buckets」(值區) 頁面

  2. 在值區清單中,按一下包含要移動物件的值區名稱。

    系統會開啟「Bucket details」(值區詳細資料) 頁面,並選取「Objects」(物件) 分頁標籤。

  3. 前往物件 (可能位於資料夾中)。

  4. 按一下與物件相關的「物件溢位」選單 ()。

  5. 如要在同一個值區中為物件重新命名,請按一下「重新命名」

    1. 在出現的重疊視窗中,為物件輸入新名稱。

    2. 按一下 [重新命名]

  6. 如要將物件移至其他值區,請按一下「移動」

    1. 在出現的重疊視窗中,按一下 [Browse] (瀏覽)。

    2. 選取要將物件移動到哪個目的地。

    3. 按一下 [選取]。

    4. 按一下 [移動]

如要瞭解如何透過 Google Cloud 控制台取得 Cloud Storage 作業失敗的詳細錯誤資訊,請參閱「疑難排解」一文。

指令列

使用 gcloud storage mv 指令:

gcloud storage mv gs://SOURCE_BUCKET_NAME/SOURCE_OBJECT_NAME gs://DESTINATION_BUCKET_NAME/DESTINATION_OBJECT_NAME

其中:

  • SOURCE_BUCKET_NAME 是包含要移動或重新命名物件的值區名稱。例如:my-bucket
  • SOURCE_OBJECT_NAME 是要移動或重新命名的物件名稱。例如:pets/dog.png
  • DESTINATION_BUCKET_NAME 是要將物件移動到的值區名稱。例如:another-bucket
  • DESTINATION_OBJECT_NAME 是您希望物件在移動或重新命名後擁有的名稱。例如:shiba.png

如果成功,回應會類似以下範例:

Copying gs://example-bucket/old-file.txt to gs://new-bucket/new-file.txt
Removing gs://example-bucket/old-file.txt...
  Completed files 1/1 | 164.3kiB/164.3kiB 

用戶端程式庫

C++

詳情請參閱 Cloud Storage C++ API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

namespace gcs = ::google::cloud::storage;
using ::google::cloud::StatusOr;
[](gcs::Client client, std::string const& bucket_name,
   std::string const& old_object_name, std::string const& new_object_name) {
  StatusOr<gcs::ObjectMetadata> metadata = client.RewriteObjectBlocking(
      bucket_name, old_object_name, bucket_name, new_object_name);
  if (!metadata) throw std::move(metadata).status();

  google::cloud::Status status =
      client.DeleteObject(bucket_name, old_object_name);
  if (!status.ok()) throw std::runtime_error(status.message());

  std::cout << "Renamed " << old_object_name << " to " << new_object_name
            << " in bucket " << bucket_name << "\n";
}

C#

詳情請參閱 Cloud Storage C# API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。


using Google.Cloud.Storage.V1;
using System;

public class MoveFileSample
{
    public void MoveFile(
        string sourceBucketName = "your-unique-bucket-name",
        string sourceObjectName = "your-object-name",
        string targetBucketName = "target-object-bucket",
        string targetObjectName = "target-object-name")
    {
        var storage = StorageClient.Create();
        storage.CopyObject(sourceBucketName, sourceObjectName, targetBucketName, targetObjectName);
        storage.DeleteObject(sourceBucketName, sourceObjectName);
        Console.WriteLine($"Moved {sourceObjectName} to {targetObjectName}.");
    }
}

Go

詳情請參閱 Cloud Storage Go API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

import (
	"context"
	"fmt"
	"io"
	"time"

	"cloud.google.com/go/storage"
)

// moveFile moves an object into another location.
func moveFile(w io.Writer, bucket, object string) error {
	// bucket := "bucket-name"
	// object := "object-name"
	ctx := context.Background()
	client, err := storage.NewClient(ctx)
	if err != nil {
		return fmt.Errorf("storage.NewClient: %w", err)
	}
	defer client.Close()

	ctx, cancel := context.WithTimeout(ctx, time.Second*10)
	defer cancel()

	dstName := object + "-rename"
	src := client.Bucket(bucket).Object(object)
	dst := client.Bucket(bucket).Object(dstName)

	// Optional: set a generation-match precondition to avoid potential race
	// conditions and data corruptions. The request to copy the file is aborted
	// if the object's generation number does not match your precondition.
	// For a dst object that does not yet exist, set the DoesNotExist precondition.
	dst = dst.If(storage.Conditions{DoesNotExist: true})
	// If the destination object already exists in your bucket, set instead a
	// generation-match precondition using its generation number.
	// attrs, err := dst.Attrs(ctx)
	// if err != nil {
	// 	return fmt.Errorf("object.Attrs: %w", err)
	// }
	// dst = dst.If(storage.Conditions{GenerationMatch: attrs.Generation})

	if _, err := dst.CopierFrom(src).Run(ctx); err != nil {
		return fmt.Errorf("Object(%q).CopierFrom(%q).Run: %w", dstName, object, err)
	}
	if err := src.Delete(ctx); err != nil {
		return fmt.Errorf("Object(%q).Delete: %w", object, err)
	}
	fmt.Fprintf(w, "Blob %v moved to %v.\n", object, dstName)
	return nil
}

Java

詳情請參閱 Cloud Storage Java API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。


import com.google.cloud.storage.Blob;
import com.google.cloud.storage.BlobId;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageOptions;

public class MoveObject {
  public static void moveObject(
      String projectId,
      String sourceBucketName,
      String sourceObjectName,
      String targetBucketName,
      String targetObjectName) {
    // The ID of your GCP project
    // String projectId = "your-project-id";

    // The ID of your GCS bucket
    // String bucketName = "your-unique-bucket-name";

    // The ID of your GCS object
    // String sourceObjectName = "your-object-name";

    // The ID of the bucket to move the object objectName to
    // String targetBucketName = "target-object-bucket"

    // The ID of your GCS object
    // String targetObjectName = "your-new-object-name";

    Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();
    BlobId source = BlobId.of(sourceBucketName, sourceObjectName);
    BlobId target = BlobId.of(targetBucketName, targetObjectName);

    // Optional: set a generation-match precondition to avoid potential race
    // conditions and data corruptions. The request returns a 412 error if the
    // preconditions are not met.
    Storage.BlobTargetOption precondition;
    if (storage.get(targetBucketName, targetObjectName) == null) {
      // For a target object that does not yet exist, set the DoesNotExist precondition.
      // This will cause the request to fail if the object is created before the request runs.
      precondition = Storage.BlobTargetOption.doesNotExist();
    } else {
      // If the destination already exists in your bucket, instead set a generation-match
      // precondition. This will cause the request to fail if the existing object's generation
      // changes before the request runs.
      precondition =
          Storage.BlobTargetOption.generationMatch(
              storage.get(targetBucketName, targetObjectName).getGeneration());
    }

    // Copy source object to target object
    storage.copy(
        Storage.CopyRequest.newBuilder().setSource(source).setTarget(target, precondition).build());
    Blob copiedObject = storage.get(target);
    // Delete the original blob now that we've copied to where we want it, finishing the "move"
    // operation
    storage.get(source).delete();

    System.out.println(
        "Moved object "
            + sourceObjectName
            + " from bucket "
            + sourceBucketName
            + " to "
            + targetObjectName
            + " in bucket "
            + copiedObject.getBucket());
  }
}

Node.js

詳情請參閱 Cloud Storage Node.js API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// The ID of your GCS bucket
// const bucketName = 'your-source-bucket';

// The ID of your GCS file
// const srcFileName = 'your-file-name';

// The new ID for your GCS file
// const destFileName = 'your-new-file-name';

// Imports the Google Cloud client library
const {Storage} = require('@google-cloud/storage');

// Creates a client
const storage = new Storage();

async function moveFile() {
  // Optional:
  // Set a generation-match precondition to avoid potential race conditions
  // and data corruptions. The request to copy is aborted if the object's
  // generation number does not match your precondition. For a destination
  // object that does not yet exist, set the ifGenerationMatch precondition to 0
  // If the destination object already exists in your bucket, set instead a
  // generation-match precondition using its generation number.
  const moveOptions = {
    preconditionOpts: {
      ifGenerationMatch: destinationGenerationMatchPrecondition,
    },
  };

  // Moves the file within the bucket
  await storage
    .bucket(bucketName)
    .file(srcFileName)
    .move(destFileName, moveOptions);

  console.log(
    `gs://${bucketName}/${srcFileName} moved to gs://${bucketName}/${destFileName}`
  );
}

moveFile().catch(console.error);

PHP

詳情請參閱 Cloud Storage PHP API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

use Google\Cloud\Storage\StorageClient;

/**
 * Move an object to a new name and/or bucket.
 *
 * @param string $bucketName The name of your Cloud Storage bucket.
 *        (e.g. 'my-bucket')
 * @param string $objectName The name of your Cloud Storage object.
 *        (e.g. 'my-object')
 * @param string $newBucketName the destination bucket name.
 *        (e.g. 'my-other-bucket')
 * @param string $newObjectName the destination object name.
 *        (e.g. 'my-other-object')
 */
function move_object(string $bucketName, string $objectName, string $newBucketName, string $newObjectName): void
{
    $storage = new StorageClient();
    $bucket = $storage->bucket($bucketName);
    $object = $bucket->object($objectName);
    $object->copy($newBucketName, ['name' => $newObjectName]);
    $object->delete();
    printf('Moved gs://%s/%s to gs://%s/%s' . PHP_EOL,
        $bucketName,
        $objectName,
        $newBucketName,
        $newObjectName);
}

Python

詳情請參閱 Cloud Storage Python API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

from google.cloud import storage


def move_blob(bucket_name, blob_name, destination_bucket_name, destination_blob_name,):
    """Moves a blob from one bucket to another with a new name."""
    # The ID of your GCS bucket
    # bucket_name = "your-bucket-name"
    # The ID of your GCS object
    # blob_name = "your-object-name"
    # The ID of the bucket to move the object to
    # destination_bucket_name = "destination-bucket-name"
    # The ID of your new GCS object (optional)
    # destination_blob_name = "destination-object-name"

    storage_client = storage.Client()

    source_bucket = storage_client.bucket(bucket_name)
    source_blob = source_bucket.blob(blob_name)
    destination_bucket = storage_client.bucket(destination_bucket_name)

    # Optional: set a generation-match precondition to avoid potential race conditions
    # and data corruptions. The request is aborted if the object's
    # generation number does not match your precondition. For a destination
    # object that does not yet exist, set the if_generation_match precondition to 0.
    # If the destination object already exists in your bucket, set instead a
    # generation-match precondition using its generation number.
    # There is also an `if_source_generation_match` parameter, which is not used in this example.
    destination_generation_match_precondition = 0

    blob_copy = source_bucket.copy_blob(
        source_blob, destination_bucket, destination_blob_name, if_generation_match=destination_generation_match_precondition,
    )
    source_bucket.delete_blob(blob_name)

    print(
        "Blob {} in bucket {} moved to blob {} in bucket {}.".format(
            source_blob.name,
            source_bucket.name,
            blob_copy.name,
            destination_bucket.name,
        )
    )

Ruby

詳情請參閱 Cloud Storage Ruby API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

def move_file bucket_name:, file_name:, new_name:
  # The ID of your GCS bucket
  # bucket_name = "your-unique-bucket-name"

  # The ID of your GCS object
  # file_name = "your-file-name"

  # The ID of your new GCS object
  # new_name = "your-new-file-name"

  require "google/cloud/storage"

  storage = Google::Cloud::Storage.new
  bucket  = storage.bucket bucket_name, skip_lookup: true
  file    = bucket.file file_name

  renamed_file = file.copy new_name

  file.delete

  puts "#{file_name} has been renamed to #{renamed_file.name}"
end

REST API

JSON API

如需透過複製作業移動或重新命名物件的 JSON API 操作說明,請參閱「複製物件」。

XML API

如需透過複製方式移動或重新命名物件的 XML API 操作說明,請參閱「複製物件」。

以原子方式重新命名物件

本節說明如何以原子方式重新命名值區中的物件。如要重新命名物件,可以使用 Cloud Storage JSON API 中的 Objects: move 方法。

REST API

JSON API

如要以原子方式重新命名物件,請按照下列步驟操作:

  1. 安裝並初始化 gcloud CLI,以便為 Authorization 標頭產生存取權杖。

  2. 使用 cURL 透過 Objects: move 要求呼叫 JSON API

    curl -X POST 
    -H "Authorization: Bearer $(gcloud auth print-access-token)"
    -H "Content-Length: 0"
    "https://storage.googleapis.com/storage/v1/b/BUCKET_NAME/o/SOURCE_OBJECT_NAME/moveTo/o/DESTINATION_OBJECT_NAME"

    其中:

    • BUCKET_NAME 是包含要重新命名物件的值區名稱。例如:my-bucket
    • SOURCE_OBJECT_NAME 是要重新命名物件的網址編碼名稱。例如: pets/dog.png,網址編碼為 pets%2Fdog.png
    • DESTINATION_OBJECT_NAME 是您要使用的網址編碼名稱。例如 pets/cat.png,網址編碼為 pets%2Fcat.png

後續步驟