Mentransfer file atau objek tertentu menggunakan manifes

Storage Transfer Service mendukung transfer file atau objek tertentu, yang ditentukan menggunakan manifes. Manifes adalah file CSV, yang diupload ke Cloud Storage, yang berisi daftar file atau objek untuk ditindaklanjuti oleh Storage Transfer Service.

Manifes dapat digunakan untuk transfer berikut:

  • Dari AWS S3, Azure Blobstore, atau Cloud Storage ke bucket Cloud Storage.

  • Dari sistem file ke bucket Cloud Storage.

  • Dari penyimpanan yang kompatibel dengan S3 ke bucket Cloud Storage.

  • Dari bucket Cloud Storage ke sistem file.

  • Antara dua sistem file.

  • Dari sumber HTTP/HTTPS yang dapat diakses secara publik ke bucket Cloud Storage. Ikuti petunjuk di Membuat daftar URL karena format manifes unik untuk daftar URL.

Membuat manifes

Manifes harus diformat sebagai CSV dan dapat berisi karakter UTF-8 apa pun. Kolom pertama harus berupa nama file atau nama objek yang ditentukan sebagai string.

File manifes tidak mendukung karakter pengganti. Nilainya harus berupa nama file atau objek tertentu. Nama folder tanpa nama file atau objek tidak didukung.

Ukuran file manifes maksimum adalah 1 GiB, yang berarti sekitar 1 juta baris. Jika perlu mentransfer file manifes yang berukuran lebih dari 1 GiB, Anda dapat membaginya menjadi beberapa file dan menjalankan beberapa tugas transfer.

Jika nama file atau objek berisi koma, nama tersebut harus diapit dalam tanda kutip ganda, sesuai dengan standar CSV. Contoh, "object1,a.txt".

Sebaiknya uji transfer Anda dengan sebagian kecil file atau objek untuk menghindari panggilan API yang tidak perlu karena error konfigurasi.

Anda dapat memantau status transfer file dari halaman Tugas Transfer. File atau objek yang gagal ditransfer akan dicantumkan dalam log transfer.

Transfer sistem file

Untuk membuat manifes file pada sistem file, buat file CSV dengan satu kolom yang berisi jalur file relatif terhadap direktori root yang ditentukan dalam pembuatan tugas transfer.

Misalnya, Anda mungkin ingin mentransfer file sistem file berikut:

Jalur file
rootdir/dir1/subdir1/file1.txt
rootdir/file2.txt
rootdir/dir2/subdir1/file3.txt

Manifes Anda akan terlihat seperti contoh berikut:

dir1/subdir1/file1.txt
file2.txt
dir2/subdir1/file3.txt

Transfer penyimpanan objek

Untuk membuat manifes objek, buat file CSV yang kolom pertamanya berisi nama objek yang terkait dengan nama bucket dan jalur yang ditentukan dalam pembuatan tugas transfer. Semua objek harus berada dalam bucket yang sama.

Anda juga dapat menentukan kolom kedua opsional dengan nomor generasi Cloud Storage dari versi tertentu yang akan ditransfer.

Misalnya, Anda mungkin ingin mentransfer objek berikut:

Jalur objek Nomor generasi Cloud Storage
SOURCE_PATH/object1.pdf 1664826685911832
SOURCE_PATH/object2.pdf
SOURCE_PATH/object3.pdf 1664826610699837

Manifes Anda akan terlihat seperti contoh berikut:

object1.pdf,1664826685911832
object2.pdf
object3.pdf,1664826610699837

Simpan file manifes dengan nama file apa pun, dan ekstensi .csv.

Transfer HTTP/HTTPS

Untuk mentransfer file tertentu dari sumber HTTP atau HTTPS, lihat petunjuk di Membuat daftar URL.

Memublikasikan manifes

Setelah membuat manifes, Anda harus menyediakannya ke Storage Transfer Service. Storage Transfer Service dapat mengakses file di bucket Cloud Storage, atau di sistem file Anda.

Mengupload manifes ke Cloud Storage

Anda dapat menyimpan file manifes di bucket Cloud Storage mana pun.

Agen layanan yang menjalankan transfer harus memiliki izin storage.objects.get untuk bucket yang berisi manifes. Lihat Memberikan izin yang diperlukan untuk mengetahui petunjuk tentang cara menemukan ID agen layanan, dan memberikan izin ke agen layanan tersebut di bucket.

Untuk petunjuk cara mengupload manifes ke bucket, lihat Mengupload objek dalam dokumentasi Cloud Storage.

Misalnya, untuk menggunakan CLI gcloud guna mengupload file ke Cloud Storage, gunakan perintah gcloud storage cp:

gcloud storage cp MANIFEST.CSV gs://DESTINATION_BUCKET_NAME/

Dengan keterangan:

  • MANIFEST.CSV adalah jalur lokal ke file manifes Anda. Contoh, Desktop/manifest01.csv.

  • DESTINATION_BUCKET_NAME adalah nama bucket tempat Anda mengupload objek. Contohnya, my-bucket.

Jika berhasil, responsnya akan terlihat seperti contoh berikut:

Completed files 1/1 | 164.3kiB/164.3kiB

Anda dapat mengenkripsi manifes menggunakan kunci enkripsi Cloud KMS yang dikelola pelanggan. Dalam hal ini, pastikan akun layanan yang mengakses manifes telah diberi kunci enkripsi yang berlaku. Kunci yang disediakan pelanggan tidak didukung.

Menyimpan manifes di sistem file

Anda dapat menyimpan file manifes di sistem file sumber atau tujuan.

Lokasi file harus dapat diakses oleh agen transfer. Jika Anda membatasi akses direktori untuk agen, pastikan file manifes berada dalam direktori yang terpasang.

Memulai transfer

Jangan ubah file manifes hingga operasi transfer selesai. Sebaiknya kunci file manifes saat transfer sedang berlangsung.

Cloud Console

Untuk memulai transfer dengan manifes dari konsol Cloud:

  1. Ikuti petunjuk di Membuat transfer untuk memilih sumber, tujuan, dan opsi.

  2. Pada langkah terakhir, Pilih setelan, centang kotak bernama Berikan daftar file yang akan ditransfer melalui file manifes.

  3. Masukkan lokasi file manifes.

gcloud

Untuk mentransfer file atau objek yang tercantum dalam manifes, sertakan flag --manifest-file=MANIFEST_FILE dengan perintah gcloud transfer jobs create Anda.

gcloud transfer jobs create SOURCE DESTINATION \
  --manifest-file=MANIFEST_FILE

MANIFEST_FILE dapat berupa salah satu nilai berikut:

  • Jalur ke file CSV di bucket Cloud Storage:

    --manifest-file=gs://my_bucket/sample_manifest.csv
    

    Lihat Mengupload manifes ke Cloud Storage untuk mengetahui detail tentang izin yang diperlukan, jika bucket atau file tidak bersifat publik.

  • Jalur relatif dari sistem file SOURCE, termasuk jalur yang ditentukan:

    --manifest-file=source://relative_path/sample_manifest.csv
    
  • Jalur relatif dari sistem file DESTINATION, termasuk jalur apa pun yang ditentukan:

    --manifest-file=destination://relative_path/sample_manifest.csv
    

REST + Library klien

REST

Untuk mentransfer file atau objek yang tercantum dalam manifes, buat panggilan API createTransferJob yang menentukan transferSpec dengan kolom transferManifest yang ditambahkan. Contoh:

POST https://storagetransfer.googleapis.com/v1/transferJobs

...
  "transferSpec": {
      "posixDataSource": {
          "rootDirectory": "/home/",
      },
      "gcsDataSink": {
          "bucketName": "GCS_NEARLINE_SINK_NAME",
          "path": "GCS_SINK_PATH",
      },
      "transferManifest": {
          "location": "gs://my_bucket/sample_manifest.csv"
      }
  }

File manifes dapat disimpan di bucket Cloud Storage, atau di sistem file sumber atau tujuan. Bucket Cloud Storage harus menggunakan awalan gs:// dan menyertakan jalur lengkap, termasuk nama bucket. Lokasi sistem file harus menggunakan awalan source:// atau destination:// dan bersifat relatif terhadap sumber atau tujuan sistem file, dan direktori utama opsional.

Go


import (
	"context"
	"fmt"
	"io"

	storagetransfer "cloud.google.com/go/storagetransfer/apiv1"
	"cloud.google.com/go/storagetransfer/apiv1/storagetransferpb"
)

func transferUsingManifest(w io.Writer, projectID string, sourceAgentPoolName string, rootDirectory string, gcsSinkBucket string, manifestBucket string, manifestObjectName string) (*storagetransferpb.TransferJob, error) {
	// Your project id
	// projectId := "myproject-id"

	// The agent pool associated with the POSIX data source. If not provided, defaults to the default agent
	// sourceAgentPoolName := "projects/my-project/agentPools/transfer_service_default"

	// The root directory path on the source filesystem
	// rootDirectory := "/directory/to/transfer/source"

	// The ID of the GCS bucket to transfer data to
	// gcsSinkBucket := "my-sink-bucket"

	// The ID of the GCS bucket that contains the manifest file
	// manifestBucket := "my-manifest-bucket"

	// The name of the manifest file in manifestBucket that specifies which objects to transfer
	// manifestObjectName := "path/to/manifest.csv"

	ctx := context.Background()
	client, err := storagetransfer.NewClient(ctx)
	if err != nil {
		return nil, fmt.Errorf("storagetransfer.NewClient: %w", err)
	}
	defer client.Close()

	manifestLocation := "gs://" + manifestBucket + "/" + manifestObjectName
	req := &storagetransferpb.CreateTransferJobRequest{
		TransferJob: &storagetransferpb.TransferJob{
			ProjectId: projectID,
			TransferSpec: &storagetransferpb.TransferSpec{
				SourceAgentPoolName: sourceAgentPoolName,
				DataSource: &storagetransferpb.TransferSpec_PosixDataSource{
					PosixDataSource: &storagetransferpb.PosixFilesystem{RootDirectory: rootDirectory},
				},
				DataSink: &storagetransferpb.TransferSpec_GcsDataSink{
					GcsDataSink: &storagetransferpb.GcsData{BucketName: gcsSinkBucket},
				},
				TransferManifest: &storagetransferpb.TransferManifest{Location: manifestLocation},
			},
			Status: storagetransferpb.TransferJob_ENABLED,
		},
	}

	resp, err := client.CreateTransferJob(ctx, req)
	if err != nil {
		return nil, fmt.Errorf("failed to create transfer job: %w", err)
	}
	if _, err = client.RunTransferJob(ctx, &storagetransferpb.RunTransferJobRequest{
		ProjectId: projectID,
		JobName:   resp.Name,
	}); err != nil {
		return nil, fmt.Errorf("failed to run transfer job: %w", err)
	}
	fmt.Fprintf(w, "Created and ran transfer job from %v to %v using manifest file %v with name %v", rootDirectory, gcsSinkBucket, manifestLocation, resp.Name)
	return resp, nil
}

Java


import com.google.storagetransfer.v1.proto.StorageTransferServiceClient;
import com.google.storagetransfer.v1.proto.TransferProto;
import com.google.storagetransfer.v1.proto.TransferTypes.GcsData;
import com.google.storagetransfer.v1.proto.TransferTypes.PosixFilesystem;
import com.google.storagetransfer.v1.proto.TransferTypes.TransferJob;
import com.google.storagetransfer.v1.proto.TransferTypes.TransferManifest;
import com.google.storagetransfer.v1.proto.TransferTypes.TransferSpec;
import java.io.IOException;

public class TransferUsingManifest {

  public static void main(String[] args) throws IOException {
    // TODO(developer): Replace these variables before running the sample.

    // Your project id
    String projectId = "my-project-id";

    // The agent pool associated with the POSIX data source. If not provided, defaults to the
    // default agent
    String sourceAgentPoolName = "projects/my-project-id/agentPools/transfer_service_default";

    // The root directory path on the source filesystem
    String rootDirectory = "/directory/to/transfer/source";

    // The ID of the GCS bucket to transfer data to
    String gcsSinkBucket = "my-sink-bucket";

    // The ID of the GCS bucket which has your manifest file
    String manifestBucket = "my-bucket";

    // The ID of the object in manifestBucket that specifies which files to transfer
    String manifestObjectName = "path/to/manifest.csv";

    transferUsingManifest(
        projectId,
        sourceAgentPoolName,
        rootDirectory,
        gcsSinkBucket,
        manifestBucket,
        manifestObjectName);
  }

  public static void transferUsingManifest(
      String projectId,
      String sourceAgentPoolName,
      String rootDirectory,
      String gcsSinkBucket,
      String manifestBucket,
      String manifestObjectName)
      throws IOException {
    String manifestLocation = "gs://" + manifestBucket + "/" + manifestObjectName;
    TransferJob transferJob =
        TransferJob.newBuilder()
            .setProjectId(projectId)
            .setTransferSpec(
                TransferSpec.newBuilder()
                    .setSourceAgentPoolName(sourceAgentPoolName)
                    .setPosixDataSource(
                        PosixFilesystem.newBuilder().setRootDirectory(rootDirectory).build())
                    .setGcsDataSink((GcsData.newBuilder().setBucketName(gcsSinkBucket)).build())
                    .setTransferManifest(
                        TransferManifest.newBuilder().setLocation(manifestLocation).build()))
            .setStatus(TransferJob.Status.ENABLED)
            .build();

    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests. After completing all of your requests, call
    // the "close" method on the client to safely clean up any remaining background resources,
    // or use "try-with-close" statement to do this automatically.
    try (StorageTransferServiceClient storageTransfer = StorageTransferServiceClient.create()) {

      // Create the transfer job
      TransferJob response =
          storageTransfer.createTransferJob(
              TransferProto.CreateTransferJobRequest.newBuilder()
                  .setTransferJob(transferJob)
                  .build());

      System.out.println(
          "Created and ran a transfer job from "
              + rootDirectory
              + " to "
              + gcsSinkBucket
              + " using "
              + "manifest file "
              + manifestLocation
              + " with name "
              + response.getName());
    }
  }
}

Node.js


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

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// Your project id
// const projectId = 'my-project'

// The agent pool associated with the POSIX data source. Defaults to the default agent
// const sourceAgentPoolName = 'projects/my-project/agentPools/transfer_service_default'

// The root directory path on the source filesystem
// const rootDirectory = '/directory/to/transfer/source'

// The ID of the GCS bucket to transfer data to
// const gcsSinkBucket = 'my-sink-bucket'

// Transfer manifest location. Must be a `gs:` URL
// const manifestLocation = 'gs://my-bucket/sample_manifest.csv'

// Creates a client
const client = new StorageTransferServiceClient();

/**
 * Creates a request to transfer from the local file system to the sink bucket
 */
async function transferViaManifest() {
  const createRequest = {
    transferJob: {
      projectId,
      transferSpec: {
        sourceAgentPoolName,
        posixDataSource: {
          rootDirectory,
        },
        gcsDataSink: {bucketName: gcsSinkBucket},
        transferManifest: {
          location: manifestLocation,
        },
      },
      status: 'ENABLED',
    },
  };

  // Runs the request and creates the job
  const [transferJob] = await client.createTransferJob(createRequest);

  const runRequest = {
    jobName: transferJob.name,
    projectId: projectId,
  };

  await client.runTransferJob(runRequest);

  console.log(
    `Created and ran a transfer job from '${rootDirectory}' to '${gcsSinkBucket}' using manifest \`${manifestLocation}\` with name ${transferJob.name}`
  );
}

transferViaManifest();

Python

from google.cloud import storage_transfer


def create_transfer_with_manifest(
    project_id: str,
    description: str,
    source_agent_pool_name: str,
    root_directory: str,
    sink_bucket: str,
    manifest_location: str,
):
    """Create a transfer from a POSIX file system to a GCS bucket using
    a manifest file."""

    client = storage_transfer.StorageTransferServiceClient()

    # The ID of the Google Cloud Platform Project that owns the job
    # project_id = 'my-project-id'

    # A useful description for your transfer job
    # description = 'My transfer job'

    # The agent pool associated with the POSIX data source.
    # Defaults to 'projects/{project_id}/agentPools/transfer_service_default'
    # source_agent_pool_name = 'projects/my-project/agentPools/my-agent'

    # The root directory path on the source filesystem
    # root_directory = '/directory/to/transfer/source'

    # Google Cloud Storage destination bucket name
    # sink_bucket = 'my-gcs-destination-bucket'

    # Transfer manifest location. Must be a `gs:` URL
    # manifest_location = 'gs://my-bucket/sample_manifest.csv'

    transfer_job_request = storage_transfer.CreateTransferJobRequest(
        {
            "transfer_job": {
                "project_id": project_id,
                "description": description,
                "status": storage_transfer.TransferJob.Status.ENABLED,
                "transfer_spec": {
                    "source_agent_pool_name": source_agent_pool_name,
                    "posix_data_source": {
                        "root_directory": root_directory,
                    },
                    "gcs_data_sink": {
                        "bucket_name": sink_bucket,
                    },
                    "transfer_manifest": {"location": manifest_location},
                },
            }
        }
    )

    result = client.create_transfer_job(transfer_job_request)
    print(f"Created transferJob: {result.name}")

Objek atau file dalam manifes tidak harus ditransfer dalam urutan yang tercantum.

Jika manifes menyertakan file yang sudah ada di tujuan, file tersebut akan dilewati kecuali jika opsi ganti objek yang sudah ada di sink ditentukan.

Jika manifes menyertakan objek yang ada dalam versi yang berbeda di tujuan, objek di tujuan akan ditimpa dengan versi sumber objek. Jika tujuannya adalah bucket dengan versi, versi baru objek akan dibuat.

Langkah selanjutnya