O Cloud Storage para Firebase permite fazer upload de arquivos de forma rápida e fácil para um bucket do Cloud Storage fornecido e gerenciado pelo Firebase.
Fazer upload de arquivos
Para fazer upload de um arquivo para o Cloud Storage, primeiro crie uma referência ao caminho completo do arquivo, incluindo o nome do arquivo.
Kotlin+KTX
// Create a storage reference from our app val storageRef = storage.reference // Create a reference to "mountains.jpg" val mountainsRef = storageRef.child("mountains.jpg") // Create a reference to 'images/mountains.jpg' val mountainImagesRef = storageRef.child("images/mountains.jpg") // While the file names are the same, the references point to different files mountainsRef.name == mountainImagesRef.name // true mountainsRef.path == mountainImagesRef.path // false
Java
// Create a storage reference from our app StorageReference storageRef = storage.getReference(); // Create a reference to "mountains.jpg" StorageReference mountainsRef = storageRef.child("mountains.jpg"); // Create a reference to 'images/mountains.jpg' StorageReference mountainImagesRef = storageRef.child("images/mountains.jpg"); // While the file names are the same, the references point to different files mountainsRef.getName().equals(mountainImagesRef.getName()); // true mountainsRef.getPath().equals(mountainImagesRef.getPath()); // false
Depois de criar uma referência apropriada, chame o método putBytes()
, putFile()
ou putStream()
para fazer upload do arquivo para o Cloud Storage.
Não é possível fazer upload de dados com referência à raiz do bucket do Cloud Storage. Sua referência deve apontar para um URL filho.
Upload de dados na memória
O método putBytes()
é a maneira mais simples de fazer upload de um arquivo para o Cloud Storage. putBytes()
pega um byte[]
e retorna um UploadTask
que você pode usar para gerenciar e monitorar o status do upload.
Kotlin+KTX
// Get the data from an ImageView as bytes imageView.isDrawingCacheEnabled = true imageView.buildDrawingCache() val bitmap = (imageView.drawable as BitmapDrawable).bitmap val baos = ByteArrayOutputStream() bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos) val data = baos.toByteArray() var uploadTask = mountainsRef.putBytes(data) uploadTask.addOnFailureListener { // Handle unsuccessful uploads }.addOnSuccessListener { taskSnapshot -> // taskSnapshot.metadata contains file metadata such as size, content-type, etc. // ... }
Java
// Get the data from an ImageView as bytes imageView.setDrawingCacheEnabled(true); imageView.buildDrawingCache(); Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos); byte[] data = baos.toByteArray(); UploadTask uploadTask = mountainsRef.putBytes(data); uploadTask.addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception exception) { // Handle unsuccessful uploads } }).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() { @Override public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { // taskSnapshot.getMetadata() contains file metadata such as size, content-type, etc. // ... } });
Como putBytes()
aceita byte[]
, é necessário que seu aplicativo mantenha todo o conteúdo de um arquivo na memória de uma só vez. Considere usar putStream()
ou putFile()
para usar menos memória.
Fazer upload de um stream
O método putStream()
é a maneira mais versátil de fazer upload de um arquivo para o Cloud Storage. putStream()
pega um InputStream
e retorna um UploadTask
que você pode usar para gerenciar e monitorar o status do upload.
Kotlin+KTX
val stream = FileInputStream(File("path/to/images/rivers.jpg")) uploadTask = mountainsRef.putStream(stream) uploadTask.addOnFailureListener { // Handle unsuccessful uploads }.addOnSuccessListener { taskSnapshot -> // taskSnapshot.metadata contains file metadata such as size, content-type, etc. // ... }
Java
InputStream stream = new FileInputStream(new File("path/to/images/rivers.jpg")); uploadTask = mountainsRef.putStream(stream); uploadTask.addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception exception) { // Handle unsuccessful uploads } }).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() { @Override public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { // taskSnapshot.getMetadata() contains file metadata such as size, content-type, etc. // ... } });
Carregar de um arquivo local
Você pode fazer upload de arquivos locais no dispositivo, como fotos e vídeos da câmera, com o método putFile()
. putFile()
pega um File
e retorna um UploadTask
que você pode usar para gerenciar e monitorar o status do upload.
Kotlin+KTX
var file = Uri.fromFile(File("path/to/images/rivers.jpg")) val riversRef = storageRef.child("images/${file.lastPathSegment}") uploadTask = riversRef.putFile(file) // Register observers to listen for when the download is done or if it fails uploadTask.addOnFailureListener { // Handle unsuccessful uploads }.addOnSuccessListener { taskSnapshot -> // taskSnapshot.metadata contains file metadata such as size, content-type, etc. // ... }
Java
Uri file = Uri.fromFile(new File("path/to/images/rivers.jpg")); StorageReference riversRef = storageRef.child("images/"+file.getLastPathSegment()); uploadTask = riversRef.putFile(file); // Register observers to listen for when the download is done or if it fails uploadTask.addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception exception) { // Handle unsuccessful uploads } }).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() { @Override public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { // taskSnapshot.getMetadata() contains file metadata such as size, content-type, etc. // ... } });
Obtenha um URL de download
Depois de fazer upload de um arquivo, você pode obter uma URL para fazer download do arquivo chamando o método getDownloadUrl()
em StorageReference
:
Kotlin+KTX
val ref = storageRef.child("images/mountains.jpg") uploadTask = ref.putFile(file) val urlTask = uploadTask.continueWithTask { task -> if (!task.isSuccessful) { task.exception?.let { throw it } } ref.downloadUrl }.addOnCompleteListener { task -> if (task.isSuccessful) { val downloadUri = task.result } else { // Handle failures // ... } }
Java
final StorageReference ref = storageRef.child("images/mountains.jpg"); uploadTask = ref.putFile(file); Task<Uri> urlTask = uploadTask.continueWithTask(new Continuation<UploadTask.TaskSnapshot, Task<Uri>>() { @Override public Task<Uri> then(@NonNull Task<UploadTask.TaskSnapshot> task) throws Exception { if (!task.isSuccessful()) { throw task.getException(); } // Continue with the task to get the download URL return ref.getDownloadUrl(); } }).addOnCompleteListener(new OnCompleteListener<Uri>() { @Override public void onComplete(@NonNull Task<Uri> task) { if (task.isSuccessful()) { Uri downloadUri = task.getResult(); } else { // Handle failures // ... } } });
Adicionar metadados de arquivo
Você também pode incluir metadados ao fazer upload de arquivos. Esses metadados contêm propriedades típicas de metadados de arquivo, como name
, size
e contentType
(comumente chamado de tipo MIME). O método putFile()
infere automaticamente o tipo MIME da extensão File
, mas você pode substituir o tipo detectado automaticamente especificando contentType
nos metadados. Se você não fornecer um contentType
e o Cloud Storage não puder inferir um padrão da extensão do arquivo, o Cloud Storage usará application/octet-stream
. Consulte a seção Usar metadados de arquivo para obter mais informações sobre metadados de arquivo.
Kotlin+KTX
// Create file metadata including the content type var metadata = storageMetadata { contentType = "image/jpg" } // Upload the file and metadata uploadTask = storageRef.child("images/mountains.jpg").putFile(file, metadata)
Java
// Create file metadata including the content type StorageMetadata metadata = new StorageMetadata.Builder() .setContentType("image/jpg") .build(); // Upload the file and metadata uploadTask = storageRef.child("images/mountains.jpg").putFile(file, metadata);
Gerenciar envios
Além de iniciar uploads, você pode pausar, retomar e cancelar uploads usando os métodos pause()
, resume()
e cancel()
. Os eventos de pausa e retomada geram mudanças de estado pause
e progress
, respectivamente. Cancelar um upload faz com que ele falhe com um erro indicando que o upload foi cancelado.
Kotlin+KTX
uploadTask = storageRef.child("images/mountains.jpg").putFile(file) // Pause the upload uploadTask.pause() // Resume the upload uploadTask.resume() // Cancel the upload uploadTask.cancel()
Java
uploadTask = storageRef.child("images/mountains.jpg").putFile(file); // Pause the upload uploadTask.pause(); // Resume the upload uploadTask.resume(); // Cancel the upload uploadTask.cancel();
Monitore o progresso do upload
Você pode adicionar ouvintes para lidar com sucesso, falha, progresso ou pausas em sua tarefa de upload:
Tipo de ouvinte | Uso típico |
---|---|
OnProgressListener | Esse ouvinte é chamado periodicamente à medida que os dados são transferidos e pode ser usado para preencher um indicador de upload/download. |
OnPausedListener | Esse ouvinte é chamado sempre que a tarefa é pausada. |
OnSuccessListener | Este ouvinte é chamado quando a tarefa é concluída com êxito. |
OnFailureListener | Este ouvinte é chamado sempre que o upload falha. Isso pode acontecer devido a tempos limite de rede, falhas de autorização ou se você cancelar a tarefa. |
OnFailureListener
é chamado com uma instância Exception
. Outros ouvintes são chamados com um objeto UploadTask.TaskSnapshot
. Este objeto é uma visão imutável da tarefa no momento em que o evento ocorreu. Um UploadTask.TaskSnapshot
contém as seguintes propriedades:
Propriedade | Tipo | Descrição |
---|---|---|
getDownloadUrl | String | Uma URL que pode ser usada para fazer download do objeto. Este é um URL público indecifrável que pode ser compartilhado com outros clientes. Este valor é preenchido quando o upload é concluído. |
getError | Exception | Se a tarefa falhar, isso terá como causa uma Exceção. |
getBytesTransferred | long | O número total de bytes que foram transferidos quando esse instantâneo foi obtido. |
getTotalByteCount | long | O número total de bytes que se espera que sejam carregados. |
getUploadSessionUri | String | Um URI que pode ser usado para continuar esta tarefa por meio de outra chamada para putFile. |
getMetadata | StorageMetadata | Antes da conclusão de um upload, estes são os metadados que estão sendo enviados ao servidor. Após a conclusão do upload, estes são os metadados retornados pelo servidor. |
getTask | UploadTask | A tarefa que criou este instantâneo. Use esta tarefa para cancelar, pausar ou retomar o upload. |
getStorage | StorageReference | O StorageReference usado para criar o UploadTask . |
Os ouvintes de eventos UploadTask
fornecem uma maneira simples e poderosa de monitorar eventos de upload.
Kotlin+KTX
// Observe state change events such as progress, pause, and resume // You'll need to import com.google.firebase.storage.component1 and // com.google.firebase.storage.component2 uploadTask.addOnProgressListener { (bytesTransferred, totalByteCount) -> val progress = (100.0 * bytesTransferred) / totalByteCount Log.d(TAG, "Upload is $progress% done") }.addOnPausedListener { Log.d(TAG, "Upload is paused") }
Java
// Observe state change events such as progress, pause, and resume uploadTask.addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() { @Override public void onProgress(UploadTask.TaskSnapshot taskSnapshot) { double progress = (100.0 * taskSnapshot.getBytesTransferred()) / taskSnapshot.getTotalByteCount(); Log.d(TAG, "Upload is " + progress + "% done"); } }).addOnPausedListener(new OnPausedListener<UploadTask.TaskSnapshot>() { @Override public void onPaused(UploadTask.TaskSnapshot taskSnapshot) { Log.d(TAG, "Upload is paused"); } });
Lidar com mudanças no ciclo de vida da atividade
Os uploads continuam em segundo plano mesmo após alterações no ciclo de vida da atividade (como apresentar uma caixa de diálogo ou girar a tela). Todos os ouvintes que você anexou também permanecerão anexados. Isso poderá causar resultados inesperados se eles forem chamados após a interrupção da atividade.
Você pode resolver esse problema inscrevendo seus ouvintes em um escopo de atividade para cancelar o registro automaticamente quando a atividade for interrompida. Em seguida, use o método getActiveUploadTasks
quando a atividade for reiniciada para obter tarefas de upload que ainda estão em execução ou concluídas recentemente.
O exemplo abaixo demonstra isso e também mostra como persistir o caminho de referência de armazenamento utilizado.
Kotlin+KTX
override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) // If there's an upload in progress, save the reference so you can query it later outState.putString("reference", storageRef.toString()) } override fun onRestoreInstanceState(savedInstanceState: Bundle) { super.onRestoreInstanceState(savedInstanceState) // If there was an upload in progress, get its reference and create a new StorageReference val stringRef = savedInstanceState.getString("reference") ?: return storageRef = Firebase.storage.getReferenceFromUrl(stringRef) // Find all UploadTasks under this StorageReference (in this example, there should be one) val tasks = storageRef.activeUploadTasks if (tasks.size > 0) { // Get the task monitoring the upload val task = tasks[0] // Add new listeners to the task using an Activity scope task.addOnSuccessListener(this) { // Success! // ... } } }
Java
@Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); // If there's an upload in progress, save the reference so you can query it later if (mStorageRef != null) { outState.putString("reference", mStorageRef.toString()); } } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); // If there was an upload in progress, get its reference and create a new StorageReference final String stringRef = savedInstanceState.getString("reference"); if (stringRef == null) { return; } mStorageRef = FirebaseStorage.getInstance().getReferenceFromUrl(stringRef); // Find all UploadTasks under this StorageReference (in this example, there should be one) List<UploadTask> tasks = mStorageRef.getActiveUploadTasks(); if (tasks.size() > 0) { // Get the task monitoring the upload UploadTask task = tasks.get(0); // Add new listeners to the task using an Activity scope task.addOnSuccessListener(this, new OnSuccessListener<UploadTask.TaskSnapshot>() { @Override public void onSuccess(UploadTask.TaskSnapshot state) { // Success! // ... } }); } }
getActiveUploadTasks
recupera todas as tarefas de upload ativas na referência fornecida e abaixo dela, portanto, você pode precisar lidar com várias tarefas.
Continuando uploads em reinicializações de processos
Se o seu processo for encerrado, todos os uploads em andamento serão interrompidos. No entanto, você pode continuar o upload assim que o processo for reiniciado, retomando a sessão de upload com o servidor. Isso pode economizar tempo e largura de banda ao não iniciar o upload desde o início do arquivo.
Para fazer isso, comece o upload via putFile
. No StorageTask
resultante, chame getUploadSessionUri
e salve o valor resultante em armazenamento persistente (como SharedPreferences).
Kotlin+KTX
uploadTask = storageRef.putFile(localFile) uploadTask.addOnProgressListener { taskSnapshot -> sessionUri = taskSnapshot.uploadSessionUri if (sessionUri != null && !saved) { saved = true // A persisted session has begun with the server. // Save this to persistent storage in case the process dies. } }
Java
uploadTask = mStorageRef.putFile(localFile); uploadTask.addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() { @Override public void onProgress(UploadTask.TaskSnapshot taskSnapshot) { Uri sessionUri = taskSnapshot.getUploadSessionUri(); if (sessionUri != null && !mSaved) { mSaved = true; // A persisted session has begun with the server. // Save this to persistent storage in case the process dies. } } });
Depois que o processo for reiniciado com um upload interrompido, chame putFile novamente. Mas dessa vez passe também pelo Uri que foi salvo.
Kotlin+KTX
// resume the upload task from where it left off when the process died. // to do this, pass the sessionUri as the last parameter uploadTask = storageRef.putFile( localFile, storageMetadata { }, sessionUri, )
Java
//resume the upload task from where it left off when the process died. //to do this, pass the sessionUri as the last parameter uploadTask = mStorageRef.putFile(localFile, new StorageMetadata.Builder().build(), sessionUri);
As sessões duram uma semana. Se você tentar retomar uma sessão após ela ter expirado ou se houver um erro, você receberá um retorno de chamada de falha. É sua responsabilidade garantir que o arquivo não tenha sido alterado entre os uploads.
Manipulação de erros
Há vários motivos pelos quais podem ocorrer erros no upload, incluindo a inexistência do arquivo local ou o usuário não ter permissão para fazer upload do arquivo desejado. Você pode encontrar mais informações sobre erros na seção Tratar erros dos documentos.
Exemplo completo
Um exemplo completo de upload com monitoramento de progresso e tratamento de erros é mostrado abaixo:
Kotlin+KTX
// File or Blob file = Uri.fromFile(File("path/to/mountains.jpg")) // Create the file metadata metadata = storageMetadata { contentType = "image/jpeg" } // Upload file and metadata to the path 'images/mountains.jpg' uploadTask = storageRef.child("images/${file.lastPathSegment}").putFile(file, metadata) // Listen for state changes, errors, and completion of the upload. // You'll need to import com.google.firebase.storage.component1 and // com.google.firebase.storage.component2 uploadTask.addOnProgressListener { (bytesTransferred, totalByteCount) -> val progress = (100.0 * bytesTransferred) / totalByteCount Log.d(TAG, "Upload is $progress% done") }.addOnPausedListener { Log.d(TAG, "Upload is paused") }.addOnFailureListener { // Handle unsuccessful uploads }.addOnSuccessListener { // Handle successful uploads on complete // ... }
Java
// File or Blob file = Uri.fromFile(new File("path/to/mountains.jpg")); // Create the file metadata metadata = new StorageMetadata.Builder() .setContentType("image/jpeg") .build(); // Upload file and metadata to the path 'images/mountains.jpg' uploadTask = storageRef.child("images/"+file.getLastPathSegment()).putFile(file, metadata); // Listen for state changes, errors, and completion of the upload. uploadTask.addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() { @Override public void onProgress(UploadTask.TaskSnapshot taskSnapshot) { double progress = (100.0 * taskSnapshot.getBytesTransferred()) / taskSnapshot.getTotalByteCount(); Log.d(TAG, "Upload is " + progress + "% done"); } }).addOnPausedListener(new OnPausedListener<UploadTask.TaskSnapshot>() { @Override public void onPaused(UploadTask.TaskSnapshot taskSnapshot) { Log.d(TAG, "Upload is paused"); } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception exception) { // Handle unsuccessful uploads } }).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() { @Override public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { // Handle successful uploads on complete // ... } });
Agora que você fez upload dos arquivos, vamos aprender como baixá-los do Cloud Storage.