Constrúyete tu propio gestor documental

Uno de los programas más utilizados en nuestro sistema de gestión es el gestor documental, como todos sabéis Sharepoint se conforma entre otras cosas como un gestor de contenidos, que permite almacenar todo tipo de documentos, pero hay veces que buscamos una mayor integración en nuestros sistemas o que simplemente no queremos depender de Sharepoint. En estos casos, desarrollar un gestor documental puede ser una buena alternativa y el trabajo para construir este programa lejos de parecer complicado es relativamente sencillo.

El gestor que os propongo se basa en el mismo sistema que utiliza sharepoint, los ficheros se serializan, se encriptan si es necesario y finalmente se guardan en una tabla de una base de datos tal y como hace sharepoint, posteriormente se leen desde la base de datos y se guardan en una ruta local o se utilizan directamente, aprovechándonos del almacenamiento en la base de datos con todas las ventajas que esto conlleva, copias de seguridad, particionado de tablas, indexación de contenidos, etc.

El gestor que vamos a desarrollar debe tener capacidad para almacenar cualquier tipo de fichero, documento Word, hojas de cálculo, archivos pdf, archivos comprimidos, emails, jpgs, archivos de autocad, etc.

Para comenzar hemos creado una tabla llamada Documentación en una base de datos independiente, porque como supondréis esta puede llegar a ser muy grande y en un momento determinado quizás tengamos que alojarla o particionarla en otro servidor por escalabilidad,  tamaño o rendimiento.

clip_image002

El campo [documento] (varbinary(max)) será el encargado de almacenar los ficheros serializados.

Buscamos un método sencillo para poder subir los archivos a la base de datos, con lo que queremos arrastrar uno o varios ficheros a un contenedor para que la aplicación pueda traspasarlos posteriormente a la BD.

Para llevar a cabo esta operación, hemos creado un formulario con el control System.Windows.Forms.WebBrowser que hace referencia a una ruta temporal en el disco, en este caso hemos mapeado una unidad temporal en nuestro PC ‘c:temporal’, aunque esta podria ser tambien una ruta compartida de red. La configuración de esta carpeta se realiza a través de la propiedad “Path” del control WebBrowser. Este control ya tiene por defecto implementados el sistema Drag & Drop, que nos permite arrastrar, copiar o pegar cualquier tipo de archivo de sistemas Windows, así podemos arrastrar varios correos desde Outlook, una hoja de cálculo de Excel o cualquier fichero simplemente utilizando el ratón, al realizar esta operación sobre los archivos seleccionados estos se mueven o se copian a la ruta temporal que hemos establecido, podemos además utilizar los atajos para copiar archivos Ctrl-c / Ctrl-v, etc.

El control se puede configurar para que muestre diferentes vistas, hemos configurado una que muestra el nombre de los archivos, su tipo, la fecha, el tamaño, esta vista se puede alterar cambiando las propiedades de la carpeta temporal.

Esta primera parte que parecía complicada queda resuelta facilmente sin apenas tener que escribir un par de lineas de código, correspondientes a la configuración del control Webbrowser.

clip_image004

Una vez hemos arrastrado los archivos y estos se copian automáticamente a la ruta temporal pasamos al proceso de verificación, en esta opción se nos permite asociar cada uno de los archivos a varios metadatos, de esta forma podemos añadir información adicional a cada elemento como una descripción más detallada, observaciones, usuario, fecha o cualquier información que nos parezca relevante.

clip_image006

Finalmente los ficheros se procesan uno a uno y se van traspasando a la base de datos, para realizar esta operación podéis utilizar Directory.GetFiles(path) que permite obtener los nombres de los archivos de una ubicación determinada y FileInfo(file) que permite obtener información detallada sobre cada uno de los ficheros, fecha de creación, tamaño, etc. No debemos olvidar guardar el nombre completo con la extensión para identificar su tipo cuando vayamos a utilizarlo. 

Con todos estos datos formados por los nombres de los ficheros, sus atributos y los metadatos que podemos variar conformamos una colección temporal, lógicamente estos se grabaran posteriormente en la base de datos con lo que tendrán que tener un campo asociado en la tabla que creamos inicialmente.

Para realizar las operaciones de serialización de un fichero utilizamos la siguiente función:

//Cargar en un array de bytes el documento.
using (FileStream archivoStream = new FileStream(file, FileMode.Open, FileAccess.Read))
{
    byte[] documento = new byte[(int) archivoStream.Length];
    archivoStream.Read(documento, 0, (int) archivoStream.Length);
}

Despues de realizar este paso, si deseamos encriptar el documento para mayor seguridad podriamos hacerlo en este punto, utilizando las librerias de .net o aprovechando Sql Server para realizar esta operación.

Posteriormente grabamos el archivo y todos los datos adjuntos al documento (Metadata) utilizando un Procedimiento almacenado.

cmdOrden.Parameters.Add("@documento", SqlDbType.VarBinary).Value = documento.Archivo;
cmdOrden.Parameters.Add("@descripcion_modulo", SqlDbType.NVarChar, 100).Value = documento.Descripcion_modulo;
cmdOrden.Parameters.Add("@descripcion", SqlDbType.NVarChar, 200).Value = documento.Descripcion;
cmdOrden.Parameters.Add("@ruta", SqlDbType.NVarChar, 200).Value = documento.Ruta;
cmdOrden.Parameters.Add("@archivo", SqlDbType.NVarChar, 200).Value = documento.Archivo;
cmdOrden.Parameters.Add("@modulo", SqlDbType.NVarChar, 50).Value = documento.Modulo;
cmdOrden.Parameters.Add("@codigoAuxiliar", SqlDbType.Int, 10).Value = documento.Codigo_auxiliar;
cmdOrden.Parameters.Add("@codigoAsociado", SqlDbType.Int, 10).Value = documento.Codigo_asociado;
cmdOrden.Parameters.Add("@usuario", SqlDbType.NChar, 5).Value = documento.Usuario;
cmdOrden.Parameters.Add("@tipo", SqlDbType.NVarChar, 100).Value = documento.Tipo;
cmdOrden.Parameters.Add("@observaciones", SqlDbType.NVarChar, 1000).Value = documento.Observaciones;
cmdOrden.Parameters.Add("@codigo", SqlDbType.Int, 10).Direction = ParameterDirection.Output;

De esta forma tan sencilla los documentos se traspasan a la base de datos.

Pensando que este proceso puede ser de varios ficheros y que además algunos pueden tener un tamaño considerable, hemos dotado al programa de un mecanismo asíncrono utilizando BackGroundWorked, de forma que si el proceso tarda un tiempo la aplicación nunca llegue a bloquearse y los usuarios puedan continuar realizando su trabajo mientras se trasladan los ficheros a la BD.

Una vez hemos procesado los ficheros, lo unicó que nos queda por hacer es explotarlos, para ello tenemos que realizar la operación inversa:

Creamos otro formulario, en nuestro caso hemos utilizado un control TreeView para poder visualizar los datos de forma jerarquica, habitualmente los documentos estan relacionados con un registro de una o varias tablas, en la foto de abajo se muestran varios registros relacionados con la ficha de un artículo. Si el usuario pulsa abrir, se lee el registro de la base de datos, se deserializa el contenido del campo [documento], se desencripta si fuera necesario y finalmente se guarda en una ruta temporal o se abre directamente en memoria. Para deserializar el documento utilizamos la siguiente función, donde [doc.Documento] hace referencia al campo de tipo byte[] de nuestra entidad y [fichero] a la ruta y nombre del archivo que se va a crear como por ejemplo ‘c:tempestadisticas.xls’.

using (FileStream archivoStream = new FileStream(fichero, FileMode.Create))
{
    archivoStream.Write(doc.Documento, 0, doc.Documento.Length);
    archivoStream.Close();
}

Finalmente abrimos el fichero, para realizar esta operación y que el programa relacionado (word, excel, outlook), realice esta operación automáticamente utilizamos la siguiente función.

if (File.Exists(fichero))
{
    Process process = new Process { StartInfo = { FileName = fichero } };
    process.Start();
}

 

clip_image008

Y voila, ya tenemos nuestro gestor documental. En nuestro caso para complementar la utilidad vamos a llamar a un webservice que nos permite almacenar el fichero también en sharepoint de manera que este accesible en los dos gestores, podemos además implementar filtros para realizar búsquedas no solo por los metadatos si no por el contenido de los ficheros, implementar un control de versiones, etc, etc., pero si continuamos al final lo que tendríamos es otro “Sharepoint”.

La ventaja de esta utilidad además de la integración con nuestro sistema y la facilidad de uso es que podemos asociar el contenido a nuestros registros de la base de datos y posteriormente visualizarlos o agruparlos en otro registro para facilitar el acceso a la información.

image

En nuestro caso cada registro de cada mantenimiento tiene accesible el gestor documental de manera que en el ejemplo de la foto posterior cada registro de artículos tiene asociados varios documentos, otra ventaja es que en ciertos mantenimientos podemos visualizar la información de forma jerárquica, por ejemplo en un cliente se verían de esta forma, con lo que acceder a la información es muy sencillo.

clip_image010

Así que animaros, construiros un pequeños gestor documental como este es muy sencillo, y permitira dotar a vuestras aplicaciones de una herramiena muy potente para centralizar y acceder a todo tipo de información.