Usar el API de Dropbox desde una App Xamarin Forms PCL
Dropbox es una de las aplicaciones más populares para el intercambio y almacenamiento de archivos en la nube. En un ordenador de escritorio resulta muy sencillo utilizarlo, puesto que está integrado en el sistema de archivos y las carpetas son como cualquier otra carpeta del sistema, de modo que se pueden gestionar usando el API habitual para el manejo de archivos. Desde un dispositivo móvil, sin embargo, es necesario usar el API de Dropbox para administrar y acceder a los archivos. En este artículo voy a mostrar cómo usarlo en una aplicación PCL de Xamarin Forms.
En los ejemplos, voy a utilizar el lenguaje CSharp y la librería Dropbox.api, que se puede instalar desde el administrador de paquetes NuGet.
Lo primero que debemos hacer es registrar nuestra aplicación en la plataforma de Dropbox. Para ello, hay que ir al sitio de Dropbox para desarrolladores y seleccionar la opción Create your app:
A continuación, seleccionaremos el tipo de API que vamos a usar en la aplicación. La opción habitual, para el API gratuito es Dropbox API:
El segundo paso consiste en seleccionar el modo de acceso. Podemos restringir el acceso de la aplicación a una sola carpeta o bien permitir el acceso a todas las carpetas:
Por último, debemos introducir un nombre para la aplicación. No todos los nombres son válidos, existen unas reglas para construirlos que se pueden consultar en esta misma web. Si introduces un nombre no válido, aparecerá un enlace hacia la página con las reglas.
Al pulsar el botón Create app aparecerá la página con la configuración de la aplicación. La información que necesitas está en la sección de claves:
La clave que usaremos para conectar es el Access token de OAuth2. Para ello, pulsaremos el botón Generate que está debajo de Generated access token:
Ya solo queda copiar este token para usarlo con el cliente para realizar la conexión. Vamos a suponer que hemos almacenado esta clave en una variable o constante de cadena llamada _accessKey. La forma de crear un cliente para conectar con el API de Dropbox es muy sencilla, la clase es DropboxClient:
DropboxClient client = new DropboxClient(_accessKey)
Listar los archivos
Una de las primeras operaciones que podemos realizar una vez establecida la conexión es obtener un listado con los archivos. El API utiliza llamadas asíncronas, que pueden realizarse usando el mecanismo async / await. El método para listar el contenido de una carpeta es ListFolderAsync, con los siguientes argumentos:
- path: ruta de la carpeta. Se utiliza el formato habitual de url. Puedes pasar una cadena vacía para listar la carpeta raíz, o bien una cadena con la ruta a una subcarpeta, como /subcarpeta/…
- recursive: tiene un valor por defecto de false, se utiliza para listar las subcarpetas de forma recursiva.
- includeMediaInfo: por defecto vale false. Se utiliza para devolver metadatos sobre los ficheros de imagen y vídeo.
- includeDeleted: por defecto vale false, en el listado se incluirán archivos que han sido eliminados.
- includeHasExplicitSharedMember: por defecto vale false, proporciona información adicional en los metadatos.
Estos parámetros también se pueden pasar empaquetados en un objeto de la clase ListFolderArg.
El listado se obtiene en una o varias páginas, dependiendo de la cantidad de archivos y carpetas a listar. EL método devuelve un objeto ListFolderResult, que tiene una propiedad HasMore que indica si existen más archivos en el listado. En caso afirmativo, para continuar con el listado se debe utilizar el método ListFolderContinueAsync.
La propiedad Entries del objeto ListFolderResult se utiliza para listar los objetos contenidos en el listado. Para cada uno de ellos se pueden comprobar las propiedades IsFile, IsFolder o IsDeleted para determinar el tipo de objecto.
Este sería, por ejemplo, el código a utilizar para listar los archivos de la carpeta raíz:
using (DropboxClient client = new DropboxClient(_accessKey))
{
try
{
bool more = true;
var list = await client.Files.ListFolderAsync("");
while (more)
{
foreach (var item in list.Entries.Where(i => i.IsFile))
{
// Tratar el archivo
}
more = list.HasMore;
if (more)
{
list = await client.Files.ListFolderContinueAsync(list.Cursor);
}
}
}
catch
{
// Tratar la excepción
}
}
Subir y descargar archivos
Subir archivos a la nube o descargarlos desde allí es sencillo con los métodos UploadAsync y DownloadAsync. Puedes utilizar un objeto Stream genérico para pasar el contenido de los archivos. Por ejemplo, este podría ser el código para descargar un archivo:
public async Task DownloadFile(string filename, Stream s)
{
using (DropboxClient client = new DropboxClient(_accessKey))
{
IDownloadResponse<FileMetadata> resp = await client.Files.DownloadAsync(filename);
Stream ds = await resp.GetContentAsStreamAsync();
await ds.CopyToAsync(s);
ds.Dispose();
}
}
Recuerda que el nombre del archivo puede contener una ruta y que esta debe tener forma de url, por lo que debe empezar siempre con el carácter /.
Para subir los archivos, si tienen un tamaño menor de 150MB, puedes utilizar el método UploadAsync. Aquí los parámetros son algo más complicados. Por un lado, está la clase WriteMode, en la cual se indica si queremos añadir, sobrescribir o actualizar un archivo, mediante las propiedades booleanas IsAdd, IsOverwrite e IsUpdate. Con la clase CommitInfo podemos agrupar los parámetros pasándoselos en el constructor:
- path: cadena de texto con la ruta y el nombre del archivo.
- mode: por defecto vale null, objeto WriteMode.
- autorename: por defecto vale false. Indica si el archivo debe ser renombrado automáticamente en caso de conflicto.
- clientModified: por defecto vale null. Objeto DateTime? Para indicar la fecha de modificación del archivo.
- mute: por defecto vale false. Se utiliza para desactivar las notificaciones del cliente de Dropbox.
Como en el caso anterior, se puede utilizar un Stream genérico para subir el archivo, por ejemplo:
public async Task UploadFile(string filename, Stream s)
{
using (DropboxClient client = new DropboxClient(_accessKey))
{
CommitInfo ci = new CommitInfo(filename);
FileMetadata resp = await client.Files.UploadAsync(ci, s);
}
}
En el objeto FileMetadata devuelto se encuentra toda la información sobre el archivo.
Para los archivos mayores de 150MB, o para subir un archivo en varios pasos, se debe iniciar una sesión con el método UploadSessionStartAsync. Cada porción del archivo se escribe usando el método UploadSessionAppendV2Async, y para finalizar, usamos el método UploadSessionFinishAsync. Este es el esquema a seguir:
// Crear un cliente
DropboxClient client = new DropboxClient(_accessKey)
// Con esta variable vamos indicando la posición
// de la siguiente porción de archivo a subir
ulong offset = 0;
// Iniciamos la sesión, se puede llamar sin argumentos, o bien escribir la
// primera proción del archivo pasando en s un Stream
UploadSessionStartResult resp = await client.Files.UploadSessionStartAsync(false,s);
// Creamos un cursor para las siguientes operaciones
UploadSessionCursor cur = new UploadSessionCursor(resp.SessionId, offset);
// Para cada nueva porción del archivo, usamos esta llamada
// s es un Stream con los datos
UploadSessionAppendArg aarg = new UploadSessionAppendArg(cur);
await client.Files.UploadSessionAppendV2Async(aarg, s);
// Para terminar, le damos un nombre al archivo y finalizamos la sesión
CommitInfo ci = new CommitInfo(filename);
UploadSessionFinishArg farg = new UploadSessionFinishArg(cur, ci);
await client.Files.UploadSessionFinishAsync(farg, s);
Eliminar archivos
Por último, para eliminar un archivo usaremos el método DeleteAsync, por ejemplo de la siguiente manera:
public async Task DeleteFile(string filename)
{
using (DropboxClient client = new DropboxClient(_accessKey))
{
await client.Files.DeleteAsync(filename);
}
}
Y esto es todo sobre los métodos básicos para acceder a los archivos. Existen otros muchos métodos en la librería que podéis consultar en la documentación de Dropbox.api.