Sube archivos con Cloud Storage en Flutter

Cloud Storage para Firebase te permite subir archivos con rapidez y facilidad a un bucket de Cloud Storage proporcionado y administrado por Firebase.

Sube archivos

Para subir un archivo a Cloud Storage, primero debes crear una referencia a la ruta de acceso completa del archivo, incluido el nombre.

// Create a storage reference from our app
final storageRef = FirebaseStorage.instance.ref();

// Create a reference to "mountains.jpg"
final mountainsRef = storageRef.child("mountains.jpg");

// Create a reference to 'images/mountains.jpg'
final mountainImagesRef = storageRef.child("images/mountains.jpg");

// While the file names are the same, the references point to different files
assert(mountainsRef.name == mountainImagesRef.name);
assert(mountainsRef.fullPath != mountainImagesRef.fullPath);

Una vez que crees una referencia apropiada, llama al método putFile(), putString() o putData() para subir el archivo a Cloud Storage.

No puedes subir datos con una referencia a la raíz del bucket de Google Cloud Storage. La referencia debe apuntar a una URL secundaria.

Sube desde un archivo

Para subir un archivo, primero debes obtener la ruta de acceso absoluta de su ubicación en el dispositivo. Por ejemplo, si existe un archivo dentro del directorio de documentos de la aplicación, usa el paquete oficial de path_provider para generar una ruta de acceso del archivo y pasarla a putFile():

Directory appDocDir = await getApplicationDocumentsDirectory();
String filePath = '${appDocDir.absolute}/file-to-upload.png';
File file = File(filePath);

try {
  await mountainsRef.putFile(file);
} on firebase_core.FirebaseException catch (e) {
  // ...
}

Sube archivos desde una string

Puedes subir datos como una string sin procesar, base64, base64url o con codificación data_url con el método putString(). Por ejemplo, para subir una string de texto codificada como una URL de datos haz lo siguiente:

String dataUrl = 'data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==';

try {
  await mountainsRef.putString(dataUrl, format: PutStringFormat.dataUrl);
} on FirebaseException catch (e) {
  // ...
}

Sube datos sin procesar

Puedes subir datos escritos de nivel inferior con el formato Uint8List para los casos en los que no sea práctico subir una string o un objeto File. En este caso, llama al método putData() con tus datos:

try {
  // Upload raw data.
  await mountainsRef.putData(data);
} on firebase_core.FirebaseException catch (e) {
  // ...
}

Obtén una URL de descarga

Después de subir un archivo, llama al método getDownloadUrl() en Reference para obtener una URL de descarga del archivo:

await mountainsRef.getDownloadURL();

Agrega metadatos de archivo

También puedes incluir metadatos cuando subas archivos. Estos metadatos contienen propiedades típicas de metadatos de archivo, como contentType (comúnmente denominadas tipos de MIME). El método putFile() infiere el tipo de MIME de forma automática a partir de la extensión de File, pero puedes especificar contentType en los metadatos para anular el tipo detectado. Si no proporcionas un contentType, y Cloud Storage no puede inferir un tipo predeterminado a partir de la extensión de archivo, este usará application/octet-stream. Consulta Usa metadatos de archivos.

try {
  await mountainsRef.putFile(file, SettableMetadata(
    contentType: "image/jpeg",
  ));
} on firebase_core.FirebaseException catch (e) {
  // ...
}

Administra las cargas

Además de iniciar cargas, puedes detener, reanudar y cancelar cargas con los métodos pause(), resume() y cancel(). Los eventos de pausa y reanudación generan cambios de estado pause y progress, respectivamente. Cuando se cancela una carga, esta falla y muestra un error que indica que se canceló.

final task = mountainsRef.putFile(largeFile);

// Pause the upload.
bool paused = await task.pause();
print('paused, $paused');

// Resume the upload.
bool resumed = await task.resume();
print('resumed, $resumed');

// Cancel the upload.
bool canceled = await task.cancel();
print('canceled, $canceled');

Supervisa el progreso de la carga

Puedes escuchar el flujo de eventos de una tarea para controlar eventos de éxito, falla, progreso o pausa en tu tarea de carga:

Tipo de evento Uso común
TaskState.running Se emite periódicamente a medida que se transfieren datos y se puede usar para propagar un indicador de carga y descarga.
TaskState.paused Se emite cada vez que se pausa la tarea.
TaskState.success Se emite cuando la tarea se completa correctamente.
TaskState.canceled Se emite siempre que se cancele la tarea.
TaskState.error Se emite cuando falla la carga. Esto puede suceder debido a tiempos de espera de la red o a errores de autorización, o si cancelas la tarea.
mountainsRef.putFile(file).snapshotEvents.listen((taskSnapshot) {
  switch (taskSnapshot.state) {
    case TaskState.running:
      // ...
      break;
    case TaskState.paused:
      // ...
      break;
    case TaskState.success:
      // ...
      break;
    case TaskState.canceled:
      // ...
      break;
    case TaskState.error:
      // ...
      break;
  }
});

Soluciona errores

Existen diferentes motivos por los que pueden producirse errores durante la carga; por ejemplo, es posible que el archivo local no exista o que el usuario no tenga permiso para subir el archivo deseado. Para obtener más información sobre los errores, consulta la sección Soluciona errores de la documentación.

Ejemplo completo

A continuación, se muestra un ejemplo completo de una carga con supervisión de progreso y manejo de errores:

final appDocDir = await getApplicationDocumentsDirectory();
final filePath = "${appDocDir.absolute}/path/to/mountains.jpg";
final file = File(filePath);

// Create the file metadata
final metadata = SettableMetadata(contentType: "image/jpeg");

// Create a reference to the Firebase Storage bucket
final storageRef = FirebaseStorage.instance.ref();

// Upload file and metadata to the path 'images/mountains.jpg'
final uploadTask = storageRef
    .child("images/path/to/mountains.jpg")
    .putFile(file, metadata);

// Listen for state changes, errors, and completion of the upload.
uploadTask.snapshotEvents.listen((TaskSnapshot taskSnapshot) {
  switch (taskSnapshot.state) {
    case TaskState.running:
      final progress =
          100.0 * (taskSnapshot.bytesTransferred / taskSnapshot.totalBytes);
      print("Upload is $progress% complete.");
      break;
    case TaskState.paused:
      print("Upload is paused.");
      break;
    case TaskState.canceled:
      print("Upload was canceled");
      break;
    case TaskState.error:
      // Handle unsuccessful uploads
      break;
    case TaskState.success:
      // Handle successful uploads on complete
      // ...
      break;
  }
});

Ahora que ya subiste archivos, veamos cómo descargarlos de Cloud Storage.