Almacenar una Imagen en una Base de Datos

Por Miguel Ortiz Falcón

Contenido

 1. Introducción
 2. Una Base de Datos de Ejemplo
 3. Construyendo una Interfaz Gráfica
 4. Almacenado la Imagen
 5. Conclusión

1. Introducción

En este artículo cubriremos el proceso de almacenar una imagen en una base de datos de SQL Server, basándonos en un ejemplo de un pequeño catálogo de 'Productos'. El almacenamiento de imágenes en bases de datos no suele ser la mejor solución para el tratamiento de imágenes en las aplicaciones enlazadas a datos; sin embargo, en algunos casos es necesaria esta práctica cuando se desea aprovechar las capacidades del SGBD que se haya elegido. Para comenzar a ejemplificar este proceso, comenzaremos a crear una base de datos de ejemplo la cual se describirá en la siguiente sección.

 

2. Una Base de Datos de Ejemplo

En una base de datos de ejemplo llamada 'Store', crearemos una tabla sencilla llamada 'Productos', cuya definición será la siguiente:

CREATE TABLE Products 
(
    id int NOT NULL ,
    name nvarchar (80) NOT NULL,
    quantity int NOT NULL,
    price smallmoney NOT NULL,
    productImage image NULL ,
    CONSTRAINT PK_Products PRIMARY KEY CLUSTERED (id) 
)

Visualmente, en el administrador corporativo, tendría el aspecto que muestra la Figura 1:

Bb972266.art259-img01-402x97(es-es,MSDN.10).jpg
Figura 1. Volver al texto.

 

3. Construyendo una Interfaz Gráfica

Construiremos una pequeña interfaz gráfica que nos servirá para obtener los datos de los productos, entre ellos, la imagen. El aspecto del formulario será el que muestra la Figura 2:

Bb972266.art259-img02-384x504(es-es,MSDN.10).jpg
Figura 2. Volver al texto.

 

4. Almacenado la Imagen

Para almacenar los datos (incluyendo la imagen) primero tenemos que ingresarlos en el formulario; para ingresar la imagen nos apoyaremos en un objeto OpenFileDialog, el que usaremos para que el usuario escoja la imagen que quiere asociar al producto, y lo mostraremos cuando el usuario haya hecho clic sobre el botón para navegar (...). Usaremos el siguiente código:

private void browseButton_Click(object sender, System.EventArgs e)
{
    // Se crea el OpenFileDialog
    OpenFileDialog dialog = new OpenFileDialog();
    // Se muestra al usuario esperando una acción
    DialogResult result = dialog.ShowDialog();
 
    // Si seleccionó un archivo (asumiendo que es una imagen lo que seleccionó)
    // la mostramos en el PictureBox de la inferfaz
    if (result == DialogResult.OK)
    {
       pictureBox.Image = Image.FromFile(dialog.FileName);
    }
}

Teniendo los datos de entrada que muestra la Figura 3, por ejemplo:

Bb972266.art259-img03-384x504(es-es,MSDN.10).jpg
Figura 3. Volver al texto.

Teniendo los datos de entrada, incluyendo la imagen y no tomando en cuenta las validaciones sobre el formulario de entrada, lo siguiente será guardar en sí los datos en la base de datos. (Esta acción se produce cuando se hace clic sobre 'Guardar'). Utilizamos el siguiente código para hacerlo:

private void saveButton_Click(object sender, System.EventArgs e)
{
    try
    {
       // Objetos de conexión y comando
       System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(@"Data Source=
(local);Initial Catalog=store;Integrated Security=SSPI");
       System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand();
 
       // Estableciento propiedades
       cmd.Connection = conn;
       cmd.CommandText = "INSERT INTO Products VALUES (@id, @name, @quantity, @price, @image)";
 
      // Creando los parámetros necesarios
       cmd.Parameters.Add("@id", System.Data.SqlDbType.Int);
       cmd.Parameters.Add("@name", System.Data.SqlDbType.NVarChar);
       cmd.Parameters.Add("@quantity", System.Data.SqlDbType.Int);
       cmd.Parameters.Add("@price", System.Data.SqlDbType.SmallMoney);
       cmd.Parameters.Add("@image", System.Data.SqlDbType.Image);
 
       // Asignando los valores a los atributos
       cmd.Parameters["@id"].Value = int.Parse(idBox.Text);
       cmd.Parameters["@name"].Value = nameBox.Text;
       cmd.Parameters["@quantity"].Value = int.Parse(quantityBox.Text);
       cmd.Parameters["@price"].Value = float.Parse(priceBox.Text);
 
       // Asignando el valor de la imagen
 
       // Stream usado como buffer
       System.IO.MemoryStream ms = new System.IO.MemoryStream();
       // Se guarda la imagen en el buffer
       pictureBox.Image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
       // Se extraen los bytes del buffer para asignarlos como valor para el 
       // parámetro.
       cmd.Parameters["@image"].Value = ms.GetBuffer();
 
       conn.Open();
       cmd.ExecuteNonQuery();
       conn.Close();
    }
    catch (System.Exception ex)
    {
       MessageBox.Show(ex.Message);
    }
}

Como puedes observar, el código usa parámetros para establecer los valores de los campos. Lo más interesante está en la parte 'Asignando el valor de la imagen', ya que se usa un flujo de memoria intermedio para extraer los bytes de la imagen (que es como realmente se guarda en la base de datos, como una secuencia de bytes). Ahora bien, una vez que se tiene el objeto MemoryStream, podemos usar el método Save() del objeto Image, para obtener los bytes de la imagen y colocarlos en un flujo, especificando el tipo de formato de la imagen. Ya con los bytes cargados en el MemoryStream lo último que tenemos que hacer es asignar realmente los bytes en el valor del parámetro, lo que se hace obteniendo el buffer del MemoryStream (los bytes) y asignarlo a la propiedad Value del parámetro.

Para referenciar a la imagen en cuestión, se obtuvo desde la propiedad Image del objeto PictureBox; esto es porque se asume que debió de haber estado cargada una imagen en el cuadro. Habrá ocasiones en las que no se desee hacer de esta forma, ya sea porque se dé una ruta directa a una imagen (en modo texto), etc. Para obtener una referencia a la imagen a almacenar para utilizar el método Save(), podría usarse el método estático Image.FromFile y se obtendría la referencia a una imagen, o también de otra forma, podrían leerse los bytes directamente del archivo de imagen, en este caso la lectura habría que llevarla a cabo "manualmente" ya que no se usaría el método Save(). Dejo a tu elección cualquiera de estas técnicas, ya que esto puede variar en distintas situaciones.

 

5. Conclusión

El almacenamiento de imágenes en bases de datos no es una técnica comúnmente utilizada, ya que incrementa drásticamente el tamaño de la misma, de cada registro, entre otros inconvenientes; normalmente solo suele almacenarse la ruta de la imagen. Sin embargo en algunas ocasiones es necesario almacenarlas cuando se quiere aprovechar las características de gestión del SGBD elegido, como por ejemplo en la definición de un plan de mantenimiento, automatizando las copias de seguridad donde incluiría todo el catálogo de imágenes junto con la copia de seguridad. La mejor elección de la forma como guardar las imágenes siempre dependerá del ambiente de operación de la aplicación.

Bb972266.Miguel_Ortiz_Falcon(es-es,MSDN.10).gif

Miguel Ortiz Falcón es Estudiante de la Ingeniería en Sistemas Computacionales del Instituto Tecnológico de Veracruz, en el que ha sido reconocido como integrante del cuadro de honor en varias oportunidades. Posee 7 años de experiencia como desarrollador y profesional independiente. Es colaborador activo del Grupo de Usuarios de C# y miembro de la Academia Latinoamericana de Seguridad Informática (ALSI), y ha actuado como ponente en conferencias de Microsoft en México. Ha obtenido 4 estrellas del programa Desarrollador Cinco Estrellas de Microsoft MSDN Latinoamérica y 2 de su nueva versión.