Fazer upload de arquivos com o Cloud Storage para C++

Com o Cloud Storage for Firebase, é possível fazer upload de arquivos com rapidez e facilidade para um bucket do Cloud Storage fornecido e gerenciado pelo Firebase.

Criar uma referência

Para fazer upload de um arquivo, primeiro crie uma referência do Cloud Storage ao local no Cloud Storage para onde você quer enviar o arquivo.

Para criar uma referência, anexe caminhos filhos à raiz do bucket do Cloud Storage:

// Create a root reference
StorageReference storage_ref = storage->GetReference();

// Create a reference to "mountains.jpg"
StorageReference mountains_ref = storage_ref.Child("mountains.jpg");

// Create a reference to 'images/mountains.jpg'
StorageReference mountain_images_ref = storage_ref.Child("images/mountains.jpg");

// While the file names are the same, the references point to different files
mountains_ref.name() == mountain_images_ref.name();           // true
mountains_ref.full_path() == mountain_images_ref.full_path(); // false

Não é possível fazer upload de dados com uma referência à raiz do bucket do Cloud Storage. Sua referência precisa apontar para um URL filho.

Fazer upload de arquivos

Assim que tiver uma referência, faça upload dos arquivos para Cloud Storage de duas maneiras:

  1. Fazer upload de um buffer de bytes na memória.
  2. Fazer upload de um caminho de arquivo que representa um arquivo no dispositivo.

Fazer upload de dados na memória

O método PutData() é a maneira mais simples de fazer upload de um arquivo para o Cloud Storage. PutData() usa um buffer de bytes e retorna um Future<Metadata> que conterá informações sobre o arquivo quando o Future for concluído. É possível usar um Controller para gerenciar seu upload e monitorar o status dele.

// Data in memory
const size_t kByteBufferSize = ...
uint8_t byte_buffer[kByteBufferSize] = { ... };

// Create a reference to the file you want to upload
StorageReference rivers_ref = storage_ref.Child("images/rivers.jpg");

// Upload the file to the path "images/rivers.jpg"
Future future = rivers_ref.PutBytes(byte_buffer, kByteBufferSize);

Neste ponto, a solicitação já foi feita, mas temos que esperar o Future ser concluído antes de fazer upload do arquivo. Como os jogos geralmente são executados em um loop e têm menos retornos de chamada do que outros apps, você normalmente terá que solicitar a conclusão.

if (future.status() != firebase::kFutureStatusPending) {
  if (future.status() != firebase::kFutureStatusComplete) {
    LogMessage("ERROR: GetData() returned an invalid future.");
    // Handle the error...
  } else if (future.Error() != firebase::storage::kErrorNone) {
    LogMessage("ERROR: GetData() returned error %d: %s", future.Error(),
               future.error_message());
    // Handle the error...
    }
  } else {
    // Metadata contains file metadata such as size, content-type, and download URL.
    Metadata* metadata = future.Result();
    std::string download_url = metadata->download_url();
  }
}

Fazer upload de um arquivo local

Você pode fazer upload de arquivos locais nos dispositivos, como fotos e vídeos da câmera, com o método PutFile(). O PutFile() usa uma std::string que representa o caminho para o arquivo e retorna um Future<Metadata> que conterá informações sobre o arquivo quando o Future for concluído. É possível usar um Controller para gerenciar seu upload e monitorar o status dele.

// File located on disk
std::string local_file = ...

// Create a reference to the file you want to upload
StorageReference rivers_ref = storage_ref.Child("images/rivers.jpg");

// Upload the file to the path "images/rivers.jpg"
Future future = rivers_ref.PutFile(localFile);

// Wait for Future to complete...

if (future.Error() != firebase::storage::kErrorNone) {
  // Uh-oh, an error occurred!
} else {
  // Metadata contains file metadata such as size, content-type, and download URL.
  Metadata* metadata = future.Result();
  std::string download_url = metadata->download_url();
}

Se você quiser gerenciar o upload ativamente, forneça um Controller aos métodos PutFile() ou PutBytes(). Isso permite que você use o controlador para observar a operação de upload em andamento. Saiba mais em Gerenciar uploads.

Adicionar metadados de arquivo

Você também pode incluir metadados ao fazer upload de arquivos. Em geral, esses metadados contêm propriedades típicas de arquivos, como name, size e content_type, frequentemente chamadas de tipo MIME. O método PutFile() infere automaticamente o tipo de conteúdo a partir da extensão do nome de arquivo, mas você pode modificar o tipo detectado automaticamente especificando content_type nos metadados. Se você não fornecer um content_type e o Cloud Storage não puder inferir um padrão pela extensão de arquivo, o Cloud Storage usará application/octet-stream. Veja mais informações sobre metadados de arquivos na seção Usar metadados de arquivos.

// Create storage reference
StorageReference mountains_ref = storage_ref.Child("images/mountains.jpg");

// Create file metadata including the content type
StorageMetadata metadata;
metadata.set_content_type("image/jpeg");

// Upload data and metadata
mountains_ref.PutBytes(data, metadata);

// Upload file and metadata
mountains_ref.PutFile(local_file, metadata);

Gerenciar uploads

Além de iniciar uploads, você pode pausar, retomar e cancelar uploads usando os métodos Pause(), Resume() e Cancel() em Controller, que podem ser opcionalmente transmitidos para os métodos PutBytes() ou PutFile().

// Start uploading a file
firebase::storage::Controller controller;
storage_ref.Child("images/mountains.jpg").PutFile(local_file, nullptr, &controller);

// Pause the upload
controller.Pause();

// Resume the upload
controller.Resume();

// Cancel the upload
controller.Cancel();

Monitorar o andamento do upload

Você pode anexar listeners aos uploads para monitorar o andamento deles.

class MyListener : public firebase::storage::Listener {
 public:
  virtual void OnProgress(firebase::storage::Controller* controller) {
    // A progress event occurred
  }
};

{
  // Start uploading a file
  MyEventListener my_listener;
  storage_ref.Child("images/mountains.jpg").PutFile(local_file, my_listener);
}

Tratamento de erros

Há uma série de motivos pelos quais erros podem ocorrer no upload, incluindo arquivo local não existente ou o usuário não ter permissão para fazer upload do arquivo desejado. Encontre mais informações sobre erros na seção Tratamento de erros da documentação.

Próximas etapas

Agora que você já sabe fazer upload de arquivos, veja como baixá-los do Cloud Storage.