Como fazer transferências por streaming

O Cloud Storage é compatível com transferências por streaming, que permitem transmitir dados de e para sua conta do Cloud Storage sem que os dados precisem ser salvos em um arquivo. A transmissão é útil quando:

  • Você quer fazer o upload de dados, mas não sabe o tamanho final no início do upload, como ao gerar os dados de upload de um processo ou ao compactar um objeto rapidamente.

  • Você quer fazer o download dos dados do Cloud Storage para um processo.

Como usar a validação da soma de verificação durante o streaming

Como uma soma de verificação só pode ser fornecida na solicitação inicial de um upload, geralmente não é viável utilizar a validação da soma de verificação do Cloud Storage durante o streaming. Recomenda-se que você sempre use a validação da soma de verificação e faça isso manualmente após a conclusão do upload por streaming. No entanto, validar após a conclusão da transferência significa que todos os dados corrompidos podem ser acessados durante o tempo necessário para confirmar e remover os dados corrompidos.

Se você precisar de uma validação de soma de verificação antes da conclusão do upload e de os dados se tornarem acessíveis, não use um upload por streaming. Use uma opção de upload diferente que realize a validação da soma de verificação antes de finalizar o objeto.

Da mesma forma, não use um download de streaming se precisar validar a soma de verificação antes da conclusão do download e dos dados se tornarem acessíveis. Isso ocorre porque os downloads por streaming usam o cabeçalho Range, e o Cloud Storage não realiza a validação da soma de verificação nessas solicitações.

Pré-requisitos

Os pré-requisitos podem variar com base na ferramenta usada:

Console

Para concluir este guia usando o Console do Google Cloud, é preciso ter as permissões de IAM adequadas. Se o bucket que você quer acessar para streaming existir em um projeto que você não criou, talvez seja necessário que o proprietário do projeto conceda um papel que contenha as permissões necessárias.

Para uma lista de permissões necessárias para ações específicas, consulte Permissões do IAM para o Console do Google Cloud.

Para ver a lista de papéis relevantes, consulte Papéis do Cloud Storage. Como alternativa, é possível criar um papel personalizado que tenha permissões mais limitadas.

Linha de comando

Para concluir este guia usando um utilitário de linha de comando, você precisa ter as permissões de IAM adequadas. Se o bucket que você quer acessar para streaming existir em um projeto que você não criou, talvez seja necessário que o proprietário do projeto conceda um papel que contenha as permissões necessárias.

Para uma lista de permissões necessárias para ações específicas, consulte Permissões do IAM para comandos gsutil.

Para ver a lista de papéis relevantes, consulte Papéis do Cloud Storage. Como alternativa, é possível criar um papel personalizado que tenha permissões mais limitadas.

Amostras de código

Para concluir este guia usando as bibliotecas de cliente do Cloud Storage, é preciso ter as permissões de IAM adequadas. Se o bucket que você quer acessar para streaming existir em um projeto que você não criou, talvez seja necessário que o proprietário do projeto conceda um papel que contenha as permissões necessárias. Salvo indicação em contrário, as solicitações de biblioteca de cliente são feitas por meio da API JSON.

Para uma lista de permissões necessárias para ações específicas, consulte Permissões do IAM para métodos JSON.

Para ver a lista de papéis relevantes, consulte Papéis do Cloud Storage. Como alternativa, é possível criar um papel personalizado que tenha permissões mais limitadas.

APIs REST

API JSON

Para concluir este guia usando a API JSON, é preciso ter as permissões do IAM adequadas. Se o bucket que você quer acessar para streaming existir em um projeto que você não criou, talvez seja necessário que o proprietário do projeto conceda um papel que contenha as permissões necessárias.

Para uma lista de permissões necessárias para ações específicas, consulte Permissões do IAM para métodos JSON.

Para ver a lista de papéis relevantes, consulte Papéis do Cloud Storage. Como alternativa, é possível criar um papel personalizado que tenha permissões mais limitadas.

Fazer streaming de um upload

Os exemplos a seguir mostram como executar um upload por streaming de um processo para um objeto do Cloud Storage:

Console

O console do Google Cloud não é compatível com uploads por streaming. Em vez disso, use a CLI gcloud.

Linha de comando

gcloud

  1. Envie os dados ao comando gcloud storage cp e use um traço para indicar o URL de origem:

    PROCESS_NAME | gcloud storage cp - gs://BUCKET_NAME/OBJECT_NAME

    Em que:

    • PROCESS_NAME é o nome do processo do qual você está coletando dados. Por exemplo, collect_measurements.
    • BUCKET_NAME é o nome do bucket que contém o objeto. Por exemplo, my_app_bucket.
    • OBJECT_NAME é o nome do objeto criado a partir dos dados. Por exemplo, data_measurements.

gsutil

  1. Envie os dados ao comando gsutil cp e use um traço para indicar o URL de origem:

    PROCESS_NAME | gsutil cp - gs://BUCKET_NAME/OBJECT_NAME

    Em que:

    • PROCESS_NAME é o nome do processo do qual você está coletando dados. Por exemplo, collect_measurements.
    • BUCKET_NAME é o nome do bucket que contém o objeto. Por exemplo, my_app_bucket.
    • OBJECT_NAME é o nome do objeto criado a partir dos dados. Por exemplo, data_measurements.

Amostras de código

C++

Para mais informações, consulte a documentação de referência da API Cloud Storage C++.

namespace gcs = ::google::cloud::storage;
using ::google::cloud::StatusOr;
[](gcs::Client client, std::string const& bucket_name,
   std::string const& object_name, int desired_line_count) {
  std::string const text = "Lorem ipsum dolor sit amet";
  gcs::ObjectWriteStream stream =
      client.WriteObject(bucket_name, object_name);

  for (int lineno = 0; lineno != desired_line_count; ++lineno) {
    // Add 1 to the counter, because it is conventional to number lines
    // starting at 1.
    stream << (lineno + 1) << ": " << text << "\n";
  }

  stream.Close();

  StatusOr<gcs::ObjectMetadata> metadata = std::move(stream).metadata();
  if (!metadata) throw std::runtime_error(metadata.status().message());
  std::cout << "Successfully wrote to object " << metadata->name()
            << " its size is: " << metadata->size()
            << "\nFull metadata: " << *metadata << "\n";
}

C#

Para mais informações, consulte a documentação de referência da API Cloud Storage C#.


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

public class UploadFileSample
{
    public void UploadFile(
        string bucketName = "your-unique-bucket-name",
        string localPath = "my-local-path/my-file-name",
        string objectName = "my-file-name")
    {
        var storage = StorageClient.Create();
        using var fileStream = File.OpenRead(localPath);
        storage.UploadObject(bucketName, objectName, null, fileStream);
        Console.WriteLine($"Uploaded {objectName}.");
    }
}

Go

Para mais informações, consulte a documentação de referência da API Cloud Storage Go.

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

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

// streamFileUpload uploads an object via a stream.
func streamFileUpload(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: %v", err)
	}
	defer client.Close()

	b := []byte("Hello world.")
	buf := bytes.NewBuffer(b)

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

	// Upload an object with storage.Writer.
	wc := client.Bucket(bucket).Object(object).NewWriter(ctx)
	wc.ChunkSize = 0 // note retries are not supported for chunk size 0.

	if _, err = io.Copy(wc, buf); err != nil {
		return fmt.Errorf("io.Copy: %v", err)
	}
	// Data can continue to be added to the file until the writer is closed.
	if err := wc.Close(); err != nil {
		return fmt.Errorf("Writer.Close: %v", err)
	}
	fmt.Fprintf(w, "%v uploaded to %v.\n", object, bucket)

	return nil
}

Java

Para mais informações, consulte a documentação de referência da API Cloud Storage Java.


import com.google.cloud.WriteChannel;
import com.google.cloud.storage.BlobId;
import com.google.cloud.storage.BlobInfo;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageOptions;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;

public class StreamObjectUpload {

  public static void streamObjectUpload(
      String projectId, String bucketName, String objectName, String contents) throws IOException {
    // 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 objectName = "your-object-name";

    // The string of contents you wish to upload
    // String contents = "Hello world!";

    Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();
    BlobId blobId = BlobId.of(bucketName, objectName);
    BlobInfo blobInfo = BlobInfo.newBuilder(blobId).build();
    byte[] content = contents.getBytes(StandardCharsets.UTF_8);
    try (WriteChannel writer = storage.writer(blobInfo)) {
      writer.write(ByteBuffer.wrap(content));
      System.out.println(
          "Wrote to " + objectName + " in bucket " + bucketName + " using a WriteChannel.");
    }
  }
}

Node.js

Para mais informações, consulte a documentação de referência da API Cloud Storage Node.js.

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

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

// The content to be uploaded in the GCS file
// const contents = 'your file content';

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

// Import Node.js stream
const stream = require('stream');

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

// Get a reference to the bucket
const myBucket = storage.bucket(bucketName);

// Create a reference to a file object
const file = myBucket.file(destFileName);

// Create a pass through stream from a string
const passthroughStream = new stream.PassThrough();
passthroughStream.write(contents);
passthroughStream.end();

async function streamFileUpload() {
  passthroughStream.pipe(file.createWriteStream()).on('finish', () => {
    // The file upload is complete
  });

  console.log(`${destFileName} uploaded to ${bucketName}`);
}

streamFileUpload().catch(console.error);

PHP

Para mais informações, consulte a documentação de referência da API Cloud Storage PHP.

use Google\Cloud\Storage\StorageClient;
use Google\Cloud\Storage\WriteStream;

/**
 * Upload a chunked file stream.
 *
 * @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 $contents The contents to upload via stream chunks.
 *        (e.g. 'these are my contents')
 */
function upload_object_stream(string $bucketName, string $objectName, string $contents): void
{
    $storage = new StorageClient();
    $bucket = $storage->bucket($bucketName);
    $writeStream = new WriteStream(null, [
        'chunkSize' => 1024 * 256, // 256KB
    ]);
    $uploader = $bucket->getStreamableUploader($writeStream, [
        'name' => $objectName,
    ]);
    $writeStream->setUploader($uploader);
    $stream = fopen('data://text/plain,' . $contents, 'r');
    while (($line = stream_get_line($stream, 1024 * 256)) !== false) {
        $writeStream->write($line);
    }
    $writeStream->close();

    printf('Uploaded %s to gs://%s/%s' . PHP_EOL, $contents, $bucketName, $objectName);
}

Python

Para mais informações, consulte a documentação de referência da API Cloud Storage Python.

from google.cloud import storage

def upload_blob_from_stream(bucket_name, file_obj, destination_blob_name):
    """Uploads bytes from a stream or other file-like object to a blob."""
    # The ID of your GCS bucket
    # bucket_name = "your-bucket-name"

    # The stream or file (file-like object) from which to read
    # import io
    # file_obj = io.BytesIO()
    # file_obj.write(b"This is test data.")

    # The desired name of the uploaded GCS object (blob)
    # destination_blob_name = "storage-object-name"

    # Construct a client-side representation of the blob.
    storage_client = storage.Client()
    bucket = storage_client.bucket(bucket_name)
    blob = bucket.blob(destination_blob_name)

    # Rewind the stream to the beginning. This step can be omitted if the input
    # stream will always be at a correct position.
    file_obj.seek(0)

    # Upload data from the stream to your bucket.
    blob.upload_from_file(file_obj)

    print(
        f"Stream data uploaded to {destination_blob_name} in bucket {bucket_name}."
    )

Ruby

Para mais informações, consulte a documentação de referência da API Cloud Storage Ruby.


# The ID of your GCS bucket
# bucket_name = "your-unique-bucket-name"

# The stream or file (file-like object) from which to read
# local_file_obj = StringIO.new "This is test data."

# Name of a file in the Storage bucket
# file_name   = "some_file.txt"

require "google/cloud/storage"

storage = Google::Cloud::Storage.new
bucket  = storage.bucket bucket_name

local_file_obj.rewind
bucket.create_file local_file_obj, file_name

puts "Stream data uploaded to #{file_name} in bucket #{bucket_name}"

APIs REST

API JSON

Para executar um upload por streaming, siga as instruções sobre como executar um upload retomável com as seguintes considerações:

  • Ao fazer upload dos próprios dados de arquivo, use um upload de vários blocos.

  • Como você não sabe o tamanho total do arquivo até chegar ao bloco final, use um * para o tamanho total do arquivo no cabeçalho Content-Range de blocos intermediários.

    Por exemplo, se o primeiro bloco do upload tiver um tamanho de 512 KiB, o cabeçalho Content-Range do bloco será bytes 0-524287/*. Se o upload tiver 64.000 bytes restantes após o primeiro bloco, envie um bloco final que contenha os bytes restantes e tenha um cabeçalho Content-Range com o valor bytes 524288-588287/588288.

API XML

Para realizar um upload por streaming, use um destes métodos:

  • Upload de várias partes da API XML

  • Um upload retomável, com os seguintes ajustes:

    • Ao fazer upload dos próprios dados de arquivo, use um upload de vários blocos.

    • Como você não sabe o tamanho total do arquivo até chegar ao bloco final, use um * para o tamanho total do arquivo no cabeçalho Content-Range de blocos intermediários.

      Por exemplo, se o primeiro bloco do upload tiver um tamanho de 512 Kib, o cabeçalho Content-Range do bloco será bytes 0-524287/*. Se o upload tiver 64.000 bytes restantes após o primeiro bloco, envie um bloco final que contenha os bytes restantes e tenha um cabeçalho Content-Range com o valor bytes 524288-588287/588288.

Fazer streaming de um download

Os exemplos a seguir mostram como realizar o download de um objeto do Cloud Storage para um processo:

Console

O console do Google Cloud não é compatível com downloads por streaming. Em vez disso, use a CLI gcloud.

Linha de comando

gcloud

  1. Execute o comando gcloud storage cp usando um traço para o URL de destino. Em seguida, direcione os dados para o processo:

    gcloud storage cp gs://BUCKET_NAME/OBJECT_NAME - | PROCESS_NAME

    Em que:

    • BUCKET_NAME é o nome do bucket que contém o objeto. Por exemplo, my_app_bucket.
    • OBJECT_NAME é o nome do objeto que você está transmitindo para o processo. Por exemplo, data_measurements.
    • PROCESS_NAME é o nome do processo no qual você está inserindo dados. Por exemplo, analyze_data.

Também é possível realizar a transferência por streaming dos dados de um objeto do Cloud Storage para um comando padrão do Linux, como sort:

gcloud storage cp gs://my_app_bucket/data_measurements - | sort

gsutil

  1. Execute o comando gsutil cp usando um traço para o URL de destino. Em seguida, direcione os dados para o processo:

    gsutil cp gs://BUCKET_NAME/OBJECT_NAME - | PROCESS_NAME

    Em que:

    • BUCKET_NAME é o nome do bucket que contém o objeto. Por exemplo, my_app_bucket.
    • OBJECT_NAME é o nome do objeto que você está transmitindo para o processo. Por exemplo, data_measurements.
    • PROCESS_NAME é o nome do processo no qual você está inserindo dados. Por exemplo, analyze_data.

Também é possível realizar a transferência por streaming dos dados de um objeto do Cloud Storage para um comando padrão do Linux, como sort:

gsutil cp gs://my_app_bucket/data_measurements - | sort

Amostras de código

C++

Para mais informações, consulte a documentação de referência da API Cloud Storage C++.

namespace gcs = ::google::cloud::storage;
[](gcs::Client client, std::string const& bucket_name,
   std::string const& object_name) {
  gcs::ObjectReadStream stream = client.ReadObject(bucket_name, object_name);

  int count = 0;
  std::string line;
  while (std::getline(stream, line, '\n')) {
    ++count;
  }

  std::cout << "The object has " << count << " lines\n";
}

C#

Para mais informações, consulte a documentação de referência da API Cloud Storage C#.


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

public class DownloadFileSample
{
    public void DownloadFile(
        string bucketName = "your-unique-bucket-name",
        string objectName = "my-file-name",
        string localPath = "my-local-path/my-file-name")
    {
        var storage = StorageClient.Create();
        using var outputFile = File.OpenWrite(localPath);
        storage.DownloadObject(bucketName, objectName, outputFile);
        Console.WriteLine($"Downloaded {objectName} to {localPath}.");
    }
}

Go

Para mais informações, consulte a documentação de referência da API Cloud Storage Go.


import (
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"time"

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

// downloadFileIntoMemory downloads an object.
func downloadFileIntoMemory(w io.Writer, bucket, object string) ([]byte, error) {
	// bucket := "bucket-name"
	// object := "object-name"
	ctx := context.Background()
	client, err := storage.NewClient(ctx)
	if err != nil {
		return nil, fmt.Errorf("storage.NewClient: %v", err)
	}
	defer client.Close()

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

	rc, err := client.Bucket(bucket).Object(object).NewReader(ctx)
	if err != nil {
		return nil, fmt.Errorf("Object(%q).NewReader: %v", object, err)
	}
	defer rc.Close()

	data, err := ioutil.ReadAll(rc)
	if err != nil {
		return nil, fmt.Errorf("ioutil.ReadAll: %v", err)
	}
	fmt.Fprintf(w, "Blob %v downloaded.\n", object)
	return data, nil
}

Java

Para mais informações, consulte a documentação de referência da API Cloud Storage Java.


import com.google.cloud.ReadChannel;
import com.google.cloud.storage.BlobId;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageOptions;
import com.google.common.io.ByteStreams;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class StreamObjectDownload {

  public static void streamObjectDownload(
      String projectId, String bucketName, String objectName, String targetFile)
      throws IOException {
    // 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 objectName = "your-object-name";

    // The path to the file to download the object to
    // String targetFile = "path/to/your/file";
    Path targetFilePath = Paths.get(targetFile);

    Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();
    try (ReadChannel reader = storage.reader(BlobId.of(bucketName, objectName));
        FileChannel targetFileChannel =
            FileChannel.open(targetFilePath, StandardOpenOption.WRITE)) {

      ByteStreams.copy(reader, targetFileChannel);

      System.out.println(
          "Downloaded object "
              + objectName
              + " from bucket "
              + bucketName
              + " to "
              + targetFile
              + " using a ReadChannel.");
    }
  }
}

Node.js

Para mais informações, consulte a documentação de referência da API Cloud Storage Node.js.

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

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

// The filename and file path where you want to download the file
// const destFileName = '/local/path/to/file.txt';

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

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

async function streamFileDownload() {
  // The example below demonstrates how we can reference a remote file, then
  // pipe its contents to a local file.
  // Once the stream is created, the data can be piped anywhere (process, sdout, etc)
  await storage
    .bucket(bucketName)
    .file(fileName)
    .createReadStream() //stream is created
    .pipe(fs.createWriteStream(destFileName))
    .on('finish', () => {
      // The file download is complete
    });

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

streamFileDownload().catch(console.error);

PHP

Para mais informações, consulte a documentação de referência da API Cloud Storage PHP.

use Google\Cloud\Storage\StorageClient;

/**
 * Download an object from Cloud Storage and save it as a local file.
 *
 * @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 $destination The local destination to save the object.
 *        (e.g. '/path/to/your/file')
 */
function download_object(string $bucketName, string $objectName, string $destination): void
{
    $storage = new StorageClient();
    $bucket = $storage->bucket($bucketName);
    $object = $bucket->object($objectName);
    $object->downloadToFile($destination);
    printf(
        'Downloaded gs://%s/%s to %s' . PHP_EOL,
        $bucketName,
        $objectName,
        basename($destination)
    );
}

Python

Para mais informações, consulte a documentação de referência da API Cloud Storage Python.

from google.cloud import storage

def download_blob_to_stream(bucket_name, source_blob_name, file_obj):
    """Downloads a blob to a stream or other file-like object."""

    # The ID of your GCS bucket
    # bucket_name = "your-bucket-name"

    # The ID of your GCS object (blob)
    # source_blob_name = "storage-object-name"

    # The stream or file (file-like object) to which the blob will be written
    # import io
    # file_obj = io.BytesIO()

    storage_client = storage.Client()

    bucket = storage_client.bucket(bucket_name)

    # Construct a client-side representation of a blob.
    # Note `Bucket.blob` differs from `Bucket.get_blob` in that it doesn't
    # retrieve metadata from Google Cloud Storage. As we don't use metadata in
    # this example, using `Bucket.blob` is preferred here.
    blob = bucket.blob(source_blob_name)
    blob.download_to_file(file_obj)

    print(f"Downloaded blob {source_blob_name} to file-like object.")

    return file_obj
    # Before reading from file_obj, remember to rewind with file_obj.seek(0).

Ruby

Para mais informações, consulte a documentação de referência da API Cloud Storage Ruby.

# Downloads a blob to a stream or other file-like object.

# The ID of your GCS bucket
# bucket_name = "your-unique-bucket-name"

# Name of a file in the Storage bucket
# file_name   = "some_file.txt"

# The stream or file (file-like object) to which the contents will be written
# local_file_obj = StringIO.new

require "google/cloud/storage"

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

file.download local_file_obj, verify: :none

# rewind the object before starting to read the downloaded contents
local_file_obj.rewind
puts "The full downloaded file contents are: #{local_file_obj.read.inspect}"

APIs REST

API JSON

Para executar um download por streaming, siga as instruções para fazer o download de um objeto com as seguintes considerações:

  • Antes de começar o download, recupere os metadados do objeto e salve o número de geração. Inclua esse número de geração em todas as suas solicitações para garantir que você não faça o download de dados de duas gerações diferentes no caso de a original ser substituída.

  • Use o cabeçalho Range na solicitação para recuperar uma parte do objeto geral, que pode ser enviada ao processo local desejado.

  • Continue fazendo solicitações para partes sucessivas do objeto até que todo o objeto seja recuperado.

API XML

Para executar um download por streaming, siga as instruções para fazer o download de um objeto com as seguintes considerações:

  • Antes de começar o download, recupere os metadados do objeto e salve o número de geração. Inclua esse número de geração em todas as suas solicitações para garantir que você não faça o download de dados de duas gerações diferentes no caso de a original ser substituída.

  • Use o cabeçalho Range na solicitação para recuperar uma parte do objeto geral, que pode ser enviada ao processo local desejado.

  • Continue fazendo solicitações para partes sucessivas do objeto até que todo o objeto seja recuperado.

A seguir