Guardar imágenes en base de datos con ASP.NET

En esta entrada vamos a ver un método para guardar imágenes físicamente en una base de datos SQL Server utilizando ASP.NET. También se podría guardar otro tipo de archivo que no sea una imagen, en este ejemplo se creará una aplicación web que permita al usuario subir cualquier tipo de imagen y guarde la información en la base de datos. Después veremos una manera para recuperar y mostrar las imágenes en un control de imagen.
Preparar estructura de datos
En SQL Server existe un tipo de datos llamado
image
preparado para almacenar imágenes directamente en una columna. En realidad es un campo binario de (2,147,483,647 bytes) de longitud por lo que también podría utilizar un tipo de datos varbinary
.
En este caso se utilizará un tipo de datos
image
.

Crear proyecto web
Abrir Visual Studio y crear un proyecto web vacio en lenguaje C# o Visual Basic.

A continuación hacer clic derecho sobre la solución y agregar un nuevo elemento al proyecto.

Seleccionar un formulario web forms o página aspx y establecerle un nombre.

Se utilizan tres controles para este ejemplo. Uno es el control
FileUpload
para permitir al usuario la subida de imágenes, el segundo control será un tipo Image
para poder cargar la imagen en él y por último un tercer control que será un Button
desde el que guardaremos la imagen en la base de datos.
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="index.aspx.vb" Inherits="index" %> <!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>
La vista de los controles será parecida a la siguiente.

El control
FileUpload
le proporciona al usuario una forma de enviar archivos desde su equipo hasta el servidor. Tiene un método HasFile
para comprobar si el usuario a seleccionado algún archivo desde su equipo. También nos proporciona acceso al propio archivo en memoria con la propiedad PostedFile
.
FileUpload1.PostedFile.InputStream
Para almacenar el archivo seleccionado en la base de datos necesitamos obtener un array de bytes del propio archivo. Podemos usar una función auxiliar para convertir un stream en una array de bytes.
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
Una vez tenemos un array de bytes podemos ejecutar una consulta de inserción para guardar la imagen.
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
Para comprobar el resultado de forma manual podemos ver que a guardado en la columna de la base de datos, si no a generado ningún error vereís algo parecido a lo 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
El siguiente paso es recuperar la imagen desde la base de datos y mostrarla en el control
Image
. Creamos una nueva página .aspx que gestionará el tratamiento de la imagen. Podemos llamarla por ejemplo imagen.aspx.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 load de la página principal tendremos que escribir el siguiente código para redirigir a la página imagen.
Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load img.ImageUrl = "imagen.aspx" End Sub
Gracias, tenia muchas horas de busqueda tratando de mostrar las imagenes
ResponderEliminarLa imagen no se muestra, no la puedo ver broder.. cómo sería??
ResponderEliminarNo entiendo la parte de la lectura, además sale error que no le capturas:
ResponderEliminar"el formato de la cadena de inicialización no se ajusta a la especificacion que comienza en el indice 0"