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 dalam Membuat daftar URL karena format manifes bersifat unik untuk daftar URL.

Membuat manifes

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

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

Ukuran file manifes maksimum adalah 1 GiB, yang berarti sekitar 1 juta baris. Jika perlu mentransfer file manifes yang lebih besar 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 subset 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 tercantum dalam log transfer.

Transfer sistem file

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

Misalnya, Anda dapat 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 relatif terhadap nama bucket dan jalur yang ditentukan dalam pembuatan tugas transfer. Semua objek harus berada di 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 pembuatan 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 dalam Membuat daftar URL.

Memublikasikan 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.

Agen layanan yang menjalankan transfer harus memiliki izin storage.objects.get untuk bucket yang berisi manifes. Lihat bagian Memberikan izin yang diperlukan untuk mendapatkan petunjuk tentang cara menemukan ID agen layanan dan memberikan izin kepada agen layanan tersebut pada bucket.

Untuk mendapatkan petunjuk tentang cara mengupload manifes ke bucket, baca artikel 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 setiap akun layanan yang mengakses manifes telah mendapatkan 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 terpasang.

Memulai transfer

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

Cloud Console

Untuk memulai transfer dengan manifes dari Konsol Cloud:

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

  2. Pada langkah terakhir, Choose settings, pilih kotak centang bernama Provide list of files to transfer via manifest file.

  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 dalam 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 apa pun yang telah ditentukan:

    --manifest-file=source://relative_path/sample_manifest.csv
    
  • Jalur relatif dari sistem file DESTINATION, termasuk jalur apa pun yang telah 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 lengkapnya, termasuk nama bucket. Lokasi sistem file harus menggunakan awalan source:// atau destination:// dan bersifat relatif terhadap sumber atau tujuan sistem file, serta 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 selalu ditransfer dalam urutan yang tercantum.

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

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

Langkah selanjutnya