ASP.NET: Guardar y leer imágenes en SQL Server

Procedimiento para guardar y leer imágenes desde una columna de BBDD en SQL Server con ASP.NET

El mismo procedimiento se puede utilizar para guardar cualquier tipo de archivo que no sea una imagen, el limite es de almacenamiento en disco y algunas extensiones de archivos que no podemos utilizar o a priori lo tenemos un poco más complicado. 🙂

En esta entrada vamos a crear una aplicación web con ASP.NET que nos valga de ejemplo para guardar y leer imágenes (archivos) directamente desde bases de datos.

Crear columna en base de datos

En SQL Server tenemos un tipo de datos image preparado para almacenar imágenes. Se comporta como un tipo de datos binario de (2,147,483,647 bytes) de longitud así que es lo mismo que utilizar un tipo de datos varbinary.

En el ejemplo utilizo un tipo de datos image pero podéis utilizar un varbinary si no vais a guardar imágenes o si queréis especificar una precisión de datos diferente.

Crear un proyecto web

Paso 1. Abrir Visual Studio y crear un proyecto web vacío en C# o Visual Basic.

Paso 2. Hacer clic derecho sobre el proyecto y seleccionar la opción de Agregar > Nuevo elemento.

Paso 3. Seleccionar y agregar un Formulario Web Forms con el nombre default.aspx.

Guardar imagen en base de datos

Vamos a necesitar tres controles en la página principal (default.aspx). El primero es el control FileUpload para permitir al usuario subir imágenes, el segundo será un tipo Image para poder mostrar la imagen y por último un control de tipo Button para guardar la imagen en la base de datos.

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="default.aspx.vb" 
Inherits="default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Guardar imagen en SQL Server</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Image runat="server" ID="img" />
        <br />
        <asp:FileUpload ID="FileUpload1" runat="server" />
        <br />
        <asp:Button runat="server" ID="btnGuardar" Text="Guardar" />
    </div>
    </form>
</body>
</html>

Cuando ejecutamos el proyecto (F5) la página default.aspx se verá de la siguiente manera.

El control FileUpload le proporciona al usuario una forma de enviar archivos desde su equipo hasta el servidor. Podemos controlar bastantes propiedades como el tamaño permitido de los archivos o las extensiones.

En este ejemplo solo usaremos la propiedad PostedFile para recuperar la imagen o el archivo en memoria.

FileUpload1.PostedFile.InputStream

Para guardar el archivo en la base de datos necesitamos convertir el Stream en un array de bytes. Para ello podemos usar la siguiente función auxiliar.

Private Function GetStreamAsByteArray(ByVal stream As Stream) As Byte()
    Dim streamLength As Integer = Convert.ToInt32(stream.Length)
    Dim fileData As Byte() = New Byte(streamLength) {}

    stream.Read(fileData, 0, streamLength)
    stream.Close()

    Return fileData
End Function

Con la función anterior podemos crear la consulta SQL para guardar la imagen enviando por parámetro el array de bytes.

Private Sub InsertarImagen(ByVal Imagen As Byte())
   Try
      Dim conexion As New SqlConnection("localhost")
      conexion.Open()
      Dim cmd As New SqlCommand("INSERT INTO PruebaImagen VALUES (@Imagen)", conexion)
      With cmd
         .Parameters.Add(New SqlParameter("@Imagen", SqlDbType.Image)).Value = Imagen
      End With
      cmd.ExecuteNonQuery()
      conexion.Close()
   Catch ex As Exception

   End Try
End Sub

El código fuente completo de la página default.aspx es el siguiente:

Imports System.IO
Imports System.Data
Imports System.Data.SqlClient

Partial Class index
    Inherits System.Web.UI.Page

    Protected Sub btnGuardar_Click(sender As Object, e As System.EventArgs) Handles btnGuardar.Click
        GuardarImagenSQL()
    End Sub

    Private Sub GuardarImagenSQL()
        Try
            If Not FileUpload1.HasFile Then
                Return
            End If

            Dim Imagen() As Byte = GetStreamAsByteArray(FileUpload1.PostedFile.InputStream)

            InsertarImagen(Imagen)
        Catch ex As Exception
        End Try
    End Sub

    Private Function GetStreamAsByteArray(ByVal stream As Stream) As Byte()
        Dim streamLength As Integer = Convert.ToInt32(stream.Length)
        Dim fileData As Byte() = New Byte(streamLength) {}

        stream.Read(fileData, 0, streamLength)
        stream.Close()

        Return fileData
    End Function

    Private Sub InsertarImagen(ByVal Imagen As Byte())
        Try
            Dim conexion As New SqlConnection("Ruta de conexión con la base de datos")
            conexion.Open()
            Dim cmd As New SqlCommand("INSERT INTO PruebaImagen VALUES (@Imagen)", conexion)
            With cmd
                .Parameters.Add(New SqlParameter("@Imagen", SqlDbType.Image)).Value = Imagen
            End With
            cmd.ExecuteNonQuery()
            conexion.Close()
        Catch ex As Exception

        End Try
    End Sub
End Class

Para asegurarnos de que la imagen o el archivo se ha guardado correctamente podemos abrir el gestor de base de datos y seleccionar las filas de la tabla afectada.

Si aparece el literal <Datos binarios> en las columnas es que se han guardado bien.

Leer imagen desde base de datos

El siguiente paso es recuperar la imagen desde la base de datos y mostrarla en el control Image.

Para ello creamos una página imagen.aspx para gestionar el tratamiento de las imágenes.

Partial Class imagen
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
        Try
            Dim conexion As New System.Data.SqlClient.SqlConnection("localhost")
            Dim cmd As New System.Data.SqlClient.SqlCommand
            Dim reader As System.Data.SqlClient.SqlDataReader
            cmd.CommandText = "SELECT TOP(1) FROM PruebaImagen"
            cmd.CommandType = System.Data.CommandType.Text
            cmd.Connection = conexion
            conexion.Open()
            reader = cmd.ExecuteReader()
            Response.ContentType = "img/png"
            If reader.Read Then
                Response.BinaryWrite(reader("IMAGEN"))
            End If
            conexion.Close()
        Catch ex As Exception

        End Try
    End Sub
End Class

En el método load de la página principal (default.aspx) tendremos que escribir el siguiente código para redirigir a la página imagen.aspx.

Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
   img.ImageUrl = "imagen.aspx"
End Sub

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *