You are on page 1of 4

Guardar Archivos Binarios en SQL Server

By bpbrainiak

Extraido de Picacodigos Mon Feb 20 2006 En mi proyecto actual, una aplicacin ASP .NET, el cliente expres el deseo de guardar en base de datos las cartas, basadas en plantillas Word y generadas mediante la aplicacin. Quieren guardarlas en la base de datos porque, al ser documentos oficiales, tienen que poder volver a imprimirse o visualizarse exactamente igual a como se crearon en su da. Por lo tanto, necesitamos un mtodo para guardar los ficheros Word en la base de datos en formato binario, como stream de datos y ser capaces de poder recuperarlos despus para su visualizacin. Nota: no es el objetivo de este post la creacin de ficheros Word desde cdigo C#. Podis usar para ello la automatizacin Word, o componentes de terceros como los publicados por Aspose, que son excelentes. Vamos a crear una tabla simple en SQL Server para alojar los documentos. Para este ejemplo, la llamaremos DocsBinarios, y tendr la siguiente estructura: Campo DocId Documento NombreDoc Tipo Nulos? Int (identity) No Image No VarChar(100) No

Es bastante autoexplicativo: el campo DocId es un campo de clave primaria autogenerado. El campo Documento es el que va a almacenar los streams de bits, es decir los propios ficheros Word en formato binario. El campo NombreDoc almacenar el nombre que se proporcion originalmente al documento cuando se gener. Despus crearemos un procedimiento almacenado, UploadDocs, que servir para guardar registros en esta tabla: CREATE PROCEDURE UploadDoc(@doc AS Image, @nombre AS VarChar(100)) AS INSERT INTO DocsBinarios (Documento, NombreDoc) values (@doc, @nombre) GO
Colorized by: CarlosAg.CodeColorizer

Tambin es bastante autoexplicativo: un simple INSERT INTO que recibe como parmetros un Image y un VarChar

Y ste es el mtodo que guarda los datos en la base de datos: private void GuardarFicheroBDD(string sRuta, string sFichero) { //Creamos un nuevo objeto de tipo FileStream para leer el fichero //Word en modo binario System.IO.FileStream fs = new FileStream(sRuta + sFichero, System.IO.FileMode.Open); //Creamos un array de bytes para almacenar los datos ledos por fs. Byte[] data = new byte[fs.Length]; //Y guardamos los datos en el array data fs.Read(data, 0, Convert.ToInt32(fs.Length)); //Abrimos una conexion. En este caso los datos de la cadena de //conexion a la base de datos se recuperan de una seccin del //fichero web.config mediante ConfigurationSettings SqlConnection cnn = new SqlConnection(ConfigurationSettings.AppSettings["conexionBD"]); cnn.Open(); //Creamos un comando de tipo StoredProcedure para invocar a //UploadDocs SqlCommand cmd = new SqlCommand(UploadDoc, cnn); cmd.CommandType = CommandType.StoredProcedure; //Aadimos los parametros esperados y los valores de los mismos cmd.Parameters.Add(@doc, data); //los datos del fichero Word cmd.Parameters.Add(@nombre, sFichero); //y su nombre //Ejecutamos el procedimiento almacenado, que inserta un nuevo //registro en DocsBinarios con los datos que queremos introducir cmd.ExecuteNonQuery(); //Cerramos la conexin y el fichero cnn.Close(); fs.Close(); }
Colorized by: CarlosAg.CodeColorizer

Ahora veamos el mtodo para recuperar esos datos de la base de datos y mostrarlos como un fichero Word: private void LeerDeBD() { //Abrimos la conexion, exactamente igual que antes SqlConnection cnn = new SqlConnection(ConfigurationSettings.AppSettings["conexionBD"]); cnn.Open(); //Este es el comando que abre el registro que deseamos. Para este //ejemplo abrimos siempre el primer registro, habra que modificar // este cdigo para que el mtodo recibiera como parmetro el

//registro que queremos abrir, claro. SqlCommand comm = new SqlCommand(SELECT * FROM DocsBinarios + WHERE docId = 1, cnn); comm.CommandType = CommandType.Text; SqlDataAdapter da = new SqlDataAdapter(comm); DataSet ds = new DataSet(Binarios); da.Fill(ds); //Creamos un array de bytes que contiene los bytes almacenados //en el campo Documento de la tabla byte[] bits = ((byte[])(ds.Tables[0].Rows[0].ItemArray[1])); cnn.Close(); //Vamos a guardar ese array de bytes como un fichero en el //disco duro, un fichero temporal que despus se podr descartar. //Para evitar problemas de concurrencia de usuarios, //generamos un nombre nico para el mismo string sFile = tmp + GenerarNombreFichero() + .doc; //Creamos un nuevo FileStream, que esta vez servir para //crear un fichero con el nombre especificado FileStream fs = new FileStream(Server.MapPath(.) + @\DocsGenerados\ + sFile, FileMode.Create); //Y escribimos en disco el array de bytes que conforman //el fichero Word fs.Write(bits, 0, Convert.ToInt32(bits.Length)); fs.Close(); //Para mostrar el fichero, utilizamos una funcin //JavaScript llamada mostrarFichero (que lo nico que //hace es cargar el fichero especificado) //y hacemos que se ejecute en un pop-up. string script = <script languaje=javascript> ; script += mostrarFichero(DocsGenerados/ + sFile + ) ; script += </script> + Environment.NewLine; Page.RegisterStartupScript(mostrarFichero,script); }
Colorized by: CarlosAg.CodeColorizer

Y listo. Mediante ste ltimo mtodo el fichero Word se carga desde la base de datos y se muestra en un popup y en todo su esplendor. Para que tengis el cdigo completo, sta es la funcin JavaScript que carga el fichero generado desde base de datos: <script language=javascript> function mostrarFichero(destino) { window.open(destino,null,directories=no,height=600, width=800,left=0,top=0,location=no,menubar=yes, status=no,toolbar=yes,resizable=yes)

document.forms(0).submit(); } </script>
Colorized by: CarlosAg.CodeColorizer

Y ste el mtodo GenerarNombreFichero(), que utiliza la cuenta de ticks del servidor para crear nombres cuasi nicos de fichero. private string GenerarNombreFichero() { int ultimoTick = 0; while(ultimoTick==Environment.TickCount) { System.Threading.Thread.Sleep(1); } ultimoTick=Environment.TickCount; return DateTime.Now.ToString(yyyyMMddhhmmss) + . + ultimoTick.ToString(); }

You might also like