Transfira ficheiros ou objetos específicos através de um manifesto

O Serviço de transferência de armazenamento suporta a transferência de ficheiros ou objetos específicos, que são especificados através de um manifesto. Um manifesto é um ficheiro CSV carregado para o Cloud Storage que contém uma lista de ficheiros ou objetos sobre os quais o Storage Transfer Service deve atuar.

Pode usar um manifesto para as seguintes transferências:

  • Do AWS S3, do armazenamento compatível com S3, do Azure Blobstore ou do Cloud Storage para um contentor do Cloud Storage.

  • De um sistema de ficheiros para um contentor do Cloud Storage.

  • De um contentor do Cloud Storage para um sistema de ficheiros.

  • Entre dois sistemas de ficheiros.

  • De uma origem HTTP/HTTPS acessível publicamente para um contentor do Cloud Storage. Siga as instruções em Criar uma lista de URLs, uma vez que o formato do manifesto é exclusivo para listas de URLs.

Crie um manifesto

Os ficheiros de manifesto têm os seguintes requisitos:

  • Os manifestos têm de estar formatados como CSV.
  • Podem conter quaisquer carateres UTF-8.
  • A primeira coluna tem de ser um nome de ficheiro ou um nome de objeto. O nome é relativo ao caminho raiz ou ao contentor e à pasta especificados na tarefa de transferência. Consulte os artigos Transferências do sistema de ficheiros e Transferências de armazenamento de objetos para ver detalhes.
  • Os ficheiros do manifesto não suportam carateres universais. Os nomes de pastas sem um nome de ficheiro ou de objeto não são suportados.
  • Se um nome de ficheiro ou de objeto contiver uma vírgula, o nome tem de estar entre aspas duplas. Por exemplo, "doe,john.txt".
  • Para transferências que usam agentes de transferência (ou seja, transferências do sistema de ficheiros ou transferências de armazenamento compatível com S3), o tamanho máximo do ficheiro de manifesto é de 1 GiB, o que se traduz em aproximadamente 1 milhão de linhas. Se o ficheiro de manifesto tiver mais de 1 GiB, pode dividi-lo em vários ficheiros e executar várias tarefas de transferência. Para transferências sem agente, não existe um limite para o tamanho do ficheiro de manifesto.

Recomendamos que teste a transferência com um pequeno subconjunto de ficheiros ou objetos para evitar chamadas de API desnecessárias devido a erros de configuração.

Pode monitorizar o estado das transferências de ficheiros na página Tarefas de transferência. Os ficheiros ou os objetos cuja transferência falha são apresentados nos registos de transferência.

Transferências de sistemas de ficheiros

Para criar um manifesto de ficheiros num sistema de ficheiros, crie um ficheiro CSV com uma única coluna que contenha os caminhos dos ficheiros relativos ao diretório raiz especificado na criação da tarefa de transferência.

Por exemplo, para transferir os seguintes ficheiros do sistema de ficheiros:

Caminho do ficheiro
rootdir/dir1/subdir1/file1.txt
rootdir/file2.txt
rootdir/dir2/subdir1/file3.txt

O manifesto deve ter um aspeto semelhante ao seguinte exemplo:

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

Guarde o ficheiro de manifesto com qualquer nome de ficheiro e uma extensão .csv.

Transferências de armazenamento de objetos

Para criar um manifesto de objetos, crie um ficheiro CSV cuja primeira coluna contenha os nomes dos objetos relativos ao nome do contentor e ao caminho especificados na criação da tarefa de transferência. Todos os objetos têm de estar no mesmo contentor.

Também pode especificar uma segunda coluna opcional com o número de geração do Cloud Storage da versão específica a transferir.

Por exemplo, pode querer transferir os seguintes objetos:

Caminho do objeto Número de geração do Cloud Storage
SOURCE_PATH/object1.pdf 1664826685911832
SOURCE_PATH/object2.pdf
SOURCE_PATH/object3.pdf 1664826610699837

O manifesto deve ter um aspeto semelhante ao seguinte exemplo:

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

Guarde o ficheiro de manifesto com qualquer nome de ficheiro e uma extensão .csv.

Transferências HTTP/HTTPS

Para transferir ficheiros específicos de uma origem HTTP ou HTTPS, consulte as instruções em Crie uma lista de URLs.

Publique o manifesto

Depois de criar o manifesto, tem de o disponibilizar ao Storage Transfer Service. O Serviço de transferência de armazenamento pode aceder ao ficheiro num contentor do Cloud Storage ou no seu sistema de ficheiros.

Carregue o manifesto para o Cloud Storage

Pode armazenar o ficheiro de manifesto em qualquer contentor do Cloud Storage.

O agente de serviço que executa a transferência tem de ter a autorização storage.objects.get para o contentor que contém o manifesto. Consulte o artigo Conceda as autorizações necessárias para obter instruções sobre como encontrar o ID do agente do serviço e conceder autorizações a esse agente do serviço num contentor.

Para obter instruções sobre como carregar o manifesto para um contentor, consulte o artigo Carregue objetos na documentação do Cloud Storage.

Por exemplo, para usar a CLI para carregar um ficheiro para o Cloud Storage, use o comando gcloud storage cp:gcloud

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

Onde:

  • MANIFEST.CSV é o caminho local para o seu ficheiro de manifesto. Por exemplo, Desktop/manifest01.csv.

  • DESTINATION_BUCKET_NAME é o nome do contentor para o qual está a carregar o seu objeto. Por exemplo, my-bucket.

Se for bem-sucedido, a resposta é semelhante ao exemplo seguinte:

Completed files 1/1 | 164.3kiB/164.3kiB

Pode encriptar um manifesto usando chaves de encriptação do Cloud KMS geridas pelo cliente. Neste caso, certifique-se de que as contas de serviço que acedem ao manifesto têm as chaves de encriptação aplicáveis atribuídas. As chaves fornecidas pelo cliente não são suportadas.

Armazene o manifesto num sistema de ficheiros

Pode armazenar o ficheiro do manifesto no sistema de ficheiros de origem ou de destino.

A localização do ficheiro tem de estar acessível aos agentes de transferência. Se restringir o acesso ao diretório para os seus agentes, certifique-se de que o ficheiro de manifesto está localizado num diretório montado.

Inicie uma transferência

Não modifique o ficheiro de manifesto até que uma operação de transferência seja concluída. Recomendamos que bloqueie o ficheiro de manifesto quando estiver a decorrer uma transferência.

Cloud Console

Para iniciar uma transferência com um manifesto a partir da Cloud Console:

  1. Siga as instruções em Criar transferências para selecionar a origem, o destino e as opções.

  2. No passo final, Escolher definições, selecione a caixa de verificação com o nome Facultar lista de ficheiros a transferir através do ficheiro de manifesto.

  3. Introduza a localização do ficheiro de manifesto.

gcloud

Para transferir os ficheiros ou os objetos listados no manifesto, inclua a flag --manifest-file=MANIFEST_FILE com o comando gcloud transfer jobs create.

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

MANIFEST_FILE pode ter qualquer um dos seguintes valores:

  • O caminho para o ficheiro CSV num contentor do Cloud Storage:

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

    Consulte o artigo Carregue o manifesto para o Cloud Storage para ver detalhes sobre as autorizações necessárias, se o contentor ou o ficheiro não for público.

  • O caminho relativo do sistema de ficheiros SOURCE, incluindo qualquer caminho especificado:

    --manifest-file=source://relative_path/sample_manifest.csv
    
  • O caminho relativo do sistema de ficheiros DESTINATION, incluindo qualquer caminho especificado:

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

REST + bibliotecas cliente

REST

Para transferir os ficheiros ou os objetos listados no manifesto, faça uma chamada à API createTransferJob que especifique um transferSpec com o campo transferManifest adicionado. Por exemplo:

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"
      }
  }

O ficheiro de manifesto pode ser armazenado num contentor do Cloud Storage ou no sistema de ficheiros de origem ou de destino. Os contentores do Cloud Storage têm de usar o prefixo gs:// e incluir o caminho completo, incluindo o nome do contentor. As localizações do sistema de ficheiros têm de usar um prefixo source:// ou destination:// e são relativas à origem ou ao destino do sistema de ficheiros e ao diretório raiz opcional.

Ir


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}")

Os objetos ou os ficheiros no manifesto não são necessariamente transferidos na ordem indicada.

Se o manifesto incluir ficheiros que já existem no destino, esses ficheiros são ignorados, a menos que a opção overwrite objects already existing in sink seja especificada.

Se o manifesto incluir objetos que existem numa versão diferente no destino, o objeto no destino é substituído pela versão de origem do objeto. Se o destino for um contentor com versões, é criada uma nova versão do objeto.

O que se segue?