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 yang akan ditindaklanjuti oleh Storage Transfer Service.

Manifes dapat digunakan untuk transfer berikut:

  • Dari AWS S3, penyimpanan yang kompatibel dengan S3, Azure Blobstore, atau Cloud Storage ke bucket Cloud Storage.

  • Dari sistem file 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

File manifes memiliki persyaratan berikut:

  • Manifes harus diformat sebagai CSV.
  • Nama tersebut dapat berisi karakter UTF-8 apa pun.
  • Kolom pertama harus berupa nama file atau nama objek. Nama ini relatif terhadap jalur root atau bucket dan folder yang ditentukan dalam tugas transfer; lihat Transfer sistem file dan Transfer penyimpanan objek untuk mengetahui detailnya.
  • File manifes tidak mendukung karakter pengganti. Nama folder tanpa nama file atau objek tidak didukung.
  • Jika nama file atau objek berisi koma, nama harus diapit tanda petik ganda. Misalnya, "doe,john.txt".
  • Untuk transfer yang menggunakan agen transfer (yaitu, transfer sistem file atau transfer dari penyimpanan yang kompatibel dengan S3), ukuran file manifes maksimum adalah 1 GiB, yang setara dengan sekitar 1 juta baris. Jika file manifes Anda lebih besar dari 1 GiB, Anda dapat membaginya menjadi beberapa file dan menjalankan beberapa tugas transfer. Untuk transfer tanpa agen, tidak ada batasan ukuran file manifes.

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 di sistem file, buat file CSV dengan satu kolom yang berisi jalur file relatif terhadap direktori root yang ditentukan dalam pembuatan tugas transfer.

Misalnya, untuk 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

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

Transfer penyimpanan objek

Untuk membuat manifes objek, buat file CSV yang kolom pertamanya berisi nama objek relatif terhadap nama dan jalur bucket yang ditentukan dalam pembuatan tugas transfer. Semua objek harus berada di 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.

Publikasikan manifes

Setelah membuat manifes, Anda harus menyediakannya untuk 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 kepada agen layanan tersebut di bucket.

Untuk mengetahui 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:

  • MANIFEST.CSV adalah jalur lokal ke file manifest 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 semua akun layanan yang mengakses manifes diberi kunci enkripsi yang berlaku. Kunci yang disediakan pelanggan tidak didukung.

Menyimpan manifes pada 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 di-mount.

Memulai transfer

Jangan ubah file manifes hingga operasi transfer selesai. Sebaiknya Anda mengunci 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 Anda.

  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 SOURCE sistem file, termasuk jalur yang ditentukan:

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

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

REST + Library klien

REST

Untuk mentransfer file atau objek yang tercantum dalam manifes, lakukan panggilan API createTransferJob yang menentukan transferSpec dengan menambahkan kolom transferManifest. 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 prefiks gs:// dan menyertakan jalur lengkap, termasuk nama bucket. Lokasi sistem file harus menggunakan awalan source:// atau destination:// dan bersifat relatif terhadap sumber sistem file atau tujuan, dan direktori root 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 timpa 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 yang diberi versi, versi baru objek akan dibuat.

Langkah berikutnya