Guardar imagen en Mysql con .Net

Escrito en Diciembre 26, 2008 por Alex

Para guardar una imagen en Mysql desde Visual Basic .Net que puede ser en su versión 2005 o 2008 necesitamos lo siguiente:

Que en la base de datos MySql esté definido un campo de tipo “longblob” Este tipo de campo nos permite guardar datos en formato binario, de tal manera que está pensado para guardar archivos de cualquier tipo, entre ellos imágenes sin importar el formato.

En este ejemplo necesitamos de un formulario que contendrá un control PictureBox para mostrar la imagenun OpenFileDialog para seleccionar la imágen desde archivo y dos controles de tipo Botón de comando, uno para llamar a el OpenFileDialog y otro para guardar la imagen en la base de datos.

El control PictureBox tiene la propiedad Size, que podemos cambiar su valor a Zoom para que nos ajuste la imagen de mejor manera.

Para guardar la imagen en la BD necesitamos convertirla a datos binarios y lo haremos con una función que utilizará el espacio de nombres System.IO. Lo mismo al obtenerla, necesitamos convertir datos binarios a imagen  también creando  otra función similar e inversa.

Como siempre necesitamos el conector MySql para .Net que está disponible en la página del fabricante o desde este post: Conectarse a MySql desde Visual Basic .Net y agregar la referencia al archivo.

Empezamos importando los espacios de nombres que utilizaremos, creamos la cadena de conexión, una cadena con la Query (Consulta Sql), los objetos MysqlConection, MysqlCommand y MysqlDataReader, una variable array de tipo Byte para almacenar los datos y una variable de tipo Image para guardar la imagen.

En este ejemplo tomamos en cuenta que tenemos una base de datos llamada “imagenes”  y un campo dentro de ella llamado “logo” y buscaremos la imagen desde un campo llamado id con valor a 1.

y aquí pongo el código explicado:

'importamos los espacios de nombres necesarios
Imports System.Data
Imports MySql.Data.MySqlClient
'este espacio IO nos servirá para manipular los datos binarios
'a manera de stream (flujo)y se usa en las funciones bytes_image e image_bytes
Imports System.IO
 
Public Class Form1
 
#Region "variables y objetos"
    'Crear cadena de conexión
    Dim ConStr As String = "server=localhost;uid=miuser;password=mipass;database=imagenes"
    'creamos Query o consulta SQL para llamar el campo que contiene la imágen
    Dim Sql As String = "Select logo from imagenes where id='1'"
    'crear objeto Conexión pasando como parámetro la cadena con los datos
    Dim Con As New MySqlConnection(ConStr)
    'crear objeto comando que se encarga de ejecutar la Query pasando
    'como parámetro la sentencia SQl o Query y el objeto que contiene conexión
    Dim Comando As New MySqlCommand(Sql, Con)
    'crear objeto DataReader que lee datos de la BD
    Dim Dr As MySqlDataReader
    'variable de datos
    Dim bDatos() As Byte
    'variable de imagen
    Dim iImagen As Image
#End Region
 
#Region "Funciones para tratar imagenes"
 
    'convertir binario a imágen
    Private Function Bytes_Imagen(ByVal Imagen As Byte()) As Image
        Try
            'si hay imagen
            If Not Imagen Is Nothing Then
                'caturar array con memorystream hacia Bin
                Dim Bin As New MemoryStream(Imagen)
                'con el método FroStream de Image obtenemos imagen
                Dim Resultado As Image = Image.FromStream(Bin)
                'y la retornamos
                Return Resultado
            Else
                Return Nothing
            End If
        Catch ex As Exception
            Return Nothing
        End Try
    End Function
    'convertir imagen a binario
    Private Function Imagen_Bytes(ByVal Imagen As Image) As Byte()
        'si hay imagen
        If Not Imagen Is Nothing Then
            'variable de datos binarios en stream(flujo)
            Dim Bin As New MemoryStream
            'convertir a bytes
            Imagen.Save(Bin, Imaging.ImageFormat.Jpeg)
            'retorna binario
            Return Bin.GetBuffer
        Else
            Return Nothing
        End If
    End Function
    Public Function UpdateLogo(ByVal Sql As String, ByVal Data() As Byte) As String
        Dim Comando As New MySqlCommand(Sql, Con)
        Comando.Parameters.AddWithValue("?imagen", Data)
 
        Try
            If Not Con Is Nothing Then Con.Close()
            Con.Open()
            Dim res As Integer = Comando.ExecuteNonQuery()
            Return res.ToString
 
        Catch ex As Exception
            Return ex.Message
        Finally
            Con.Close()
            Comando = Nothing
        End Try
    End Function
 
#End Region
    'Esto ocurre en la carga del formulario
    'y solo se ejecuta cuando ya existe una imagen en la BD
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'Si no hay conexión activa se establece conexión con la BD
        'siempre capturando errores con try
        Try
            If Not Con Is Nothing Then Con.Close()
            Con.Open()
 
            'Una vez establecida la conexión ejecutamos la Query
            'asignando el resultado al objeto MysqlDataReader
            Dr = Comando.ExecuteReader
 
            'Mientras este leyendo, cada resultado que por la Query
            ' no es mayor a uno
            While Dr.Read
                'lo guardamos en una variable de tipo array de bytes
                'y convertimos en byte el resultado por si tenemos
                'activado Option Strict en ON
                bDatos = CType(Dr("logo_img"), Byte())
 
                'si la consulta no genera datos salimos del Sub
                If bDatos.Length = 0 Then Exit Sub
 
                'SI HAY DATOS
                'al ser datos binarios, los convertimos a imagen
                'con una funcion que hicimos llamada bytes_imagen
                'asignandolo a la variable de imagen
                iImagen = Bytes_Imagen(bDatos)
 
                'por último mostramos la imagen en el PictureBox
                PictureBox1.Image = iImagen
            End While
 
            'en caso de error mostramos el mensaje
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
 
    End Sub
 
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        'utilizamos el OPenFileDialog para seleccionar imagenes
        'Establecemos titulo a mostrar
        Me.OpenFileDialog1.Title = "Seleccionar imágen"
        'aquí por ser imagen les recomiendo abrir por default la carpeta
        'mis imagenes y utilizamos una variable de entorno de windows
        'Enviroment.SpecialFolder.MyPictures apunta a mis imagenes
        Me.OpenFileDialog1.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)
        'filtramos solo imágenes de tipo JPG pero pueden ser cualquiera
        'siempre es recomendable filtrar para evitar errores al seleccionar archivos
        Me.OpenFileDialog1.Filter = "Archivos de imágen(*.jpg)|*.jpg"
        ' abrir el diálogo
        Me.OpenFileDialog1.ShowDialog()
    End Sub
 
    'AQUI UTILIZAMOS EL EVENTO FILE_OK
    'PARA SABER EN QUE MOMENTO YA SE SELECCIONO UNA IMAGEN
    Private Sub OpenFileDialog1_FileOk(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles OpenFileDialog1.FileOk
        'obtener la imagen y mostrarla al pictureBox1
        PictureBox1.ImageLocation = OpenFileDialog1.FileName
    End Sub
 
    'Y EN ESTE EVENTO DEL BOTON GUARDAMOS LA IMAGEN EN LA BD
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Try
            'si se seleccionó archivo
            If OpenFileDialog1.FileName <> "" Then
                'variable para datos
                Dim Img() As Byte
                'convertir imagen a binario
                'y guardar en variable
                Img = Imagen_Bytes(PictureBox1.Image)
 
                'guardar la imagen en BD con parametros utilizando una funcion para guardar
                'llamada Update Logo
                Dim res As String = UpdateLogo("UPDATE datosgenerales SET logo_img=?imagen WHERE id='1'", Img)
 
                'aqui comprobamos si se modifico algun campo
                If res = "1" Then
                    MsgBox("Imagen guardada")
                Else
                    MsgBox("Imagen no se guardó")
                End If
 
            End If
        Catch ex As Exception
        End Try
    End Sub
End Class

Es recomendable que las imágenes que se guarden en la base de datos sean JPG y evitar los BMP debido a que su tamaño puede afectar el rendimiento de la BD.

Si te gusto este artículo Suscribete a nuestro feed

42 Comentarios en “Guardar imagen en Mysql con .Net”

  1. Leandro |

    Muy buen articulo, necesitaba algo parecido, muchas gracias por el post

  2. RyDer |

    Gracias por el post.
    Aunque mi pregunta es: Esto se puede hacer para archivos PDF? Si no es asi, que me tocaría utilizar?
    Gracias

  3. Alex |

    RyDer:
    Es muy parecido, Solo que necesitamos hacer algunos ajustes.
    El ejemplo te lo pongo en el post siguiente ahorita mismo.

    Pero yo no te recomiendo que guardes archivos pdf en mysql porque puede afectar el rendimiento de la Base de datos, además, hay archivos que son muy grandes y mysql ya no permite que se guarden y te puede ocasionar errores.

  4. RyDer |

    Lo que pasa Alex, es que no necesito guardalos en MySQL, ya que estan guardados.
    Te explico mi caso:
    El archivo PDF esta guardado en codigo binario en un modulo de SAP. Yo obtengo los datos y los concateno (ya que vienen en varios campos y varios registros) en una sola variable String (ya que es el unico tipo de datos que devuelve SAP). El detalle esta en que, aunque capturo los datos, los mando a escribir y el archivo lo genera, me sale el documento en blanco y un error diciendome “Error al leer el documento”.
    Ya lo he intentado con varias cosas, pero hasta ahora nada funciona. Voy a probar el metodo que colocaste en el siguiente post y si no me funciona, te lo aviso desde ese post.
    Gracias por todo.

  5. Alex |

    Hola RyDer. No se si la concatenación que haces sea efectiva, pero estoy casi seguro que el problema anda por ahí.
    De hecho la escritura del archivo no es binario puro de unos y ceros (10101010) sino la interpretación de estos en texto plano. Además, es posible que al hacer la concatenación, no se esten respetando tabuladores, retornos de carro(Enter) o saltos de linea y te lo esté escribiendo en una sola linea de corrido.

    Para salir de dudas realice lo siguiente:
    Convertí un archivo PDF a binario con estas lineas dentro de un botón:

    Dim PDF() As Byte
    PDF = PDF_Bytes(”c:\pruebas\archivo.pdf”) ‘aquí debe estar guardao el archivo PDF
    Dim oFileStream As FileStream
    ‘ y en esta ruta queda guardado de manera binaria
    oFileStream = New FileStream(”c:\pruebas\archivo.bin”, FileMode.CreateNew)
    oFileStream.Write(PDF, 0, PDF.Length)
    oFileStream.Close()
    oFileStream = Nothing

    Después lo volvi a leer desde el archivo binario para reconvertirlo a PDF

    Dim oFileStream As FileStream
    oFileStream = New FileStream(”c:\pruebas\archivo.bin”, FileMode.Open)
    Dim Valor() As Byte
    ReDim Valor(0 To CInt(oFileStream.Length))
    oFileStream.Read(Valor, 0, Valor.Length)

    ‘utilizando la función que puse en el nuevo post y que carga el resultado en el control visor de PDFs

    Bytes_PDF(Valor)

    Y me mostro el archivo de nuevo.
    Estaria bien que realizaras esta prueba y compararas tu archivo binario que resulta de la concatenación que haces desde SAP y el archivo binario del mismo archivo que resulta de esta función para ver si son iguales en tamaño y en contenido.

  6. Dantors |

    Hola Alex

    Estoy muy agradecido por tu ayuda en mi proyecto de escuela todo salio muy biem y me dieron una buena calificacion. Gracias aprendi mucho de tu Post….

    Sabes ahora me entro la curiosidad sobre programar en visual y tengo pensado realizar un checador de entrada y salida con ayuda de un lector de huella digital….ahora no se si este Post pueda ser de ayuda…ya que me imagino que la imagen de la huella digital debe ser la clave primaria en mysql, para poder asi realizar las comparciones pertinentes…

    o bueno esa es la idea que tengo…no se tu como le harias

    Saludos…

  7. Alex |

    Nunca he hecho esto y tal vez no pueda ayudarte mucho, pero empalmar imágenes para encontrar una que corresponda no es un modo práctico de comparar las huellas digitales, porque una imagen borrosa de la misma huella puede parecer una imagen diferente y es raro que obtengas un empalme perfecto. Por otro lado, utilizar una imagen completa de la huella requiere de muchos recursos del procesador y es más fácil robar datos impresos de alguien.

    Aquí un poco de info:

    La mayoría de los lectores compara rasgos específicos de la huella digital, generalmente conocidos como minutiae. Típicamente, los investigadores humanos y computadoras se concentran en puntos donde las líneas de las crestas terminan o donde se separan en dos (bifurcaciones). Colectivamente estos y otros rasgos distintivos se llaman typica.

    El software del sistema del lector utiliza algoritmos altamente complejos para reconocer y analizar estas minutiae. La idea básica es medir las posiciones relativas de la minutiae. Una manera simple de pensar en esto es considerar las figuras que varios minutia forman cuando dibuja líneas rectas entre ellas. Si dos imágenes tienen tres terminaciones de crestas y dos bifurcaciones formando la misma figura dentro de la misma dimensión, hay una gran probabilidad de que sean de la misma persona.

    Entonces dos lecturas simultaneas de una misma huella pueden dar como resultado dos huellas distintas, tienes como factor la inclinación del dedo, la presión del usuario etc.
    Busca en el sitio web de tu proveedor del equipo lector, puede ser que dispongan de un componente para desarrolladores que en muchos casos se llama SDK, ya que con el podrás obtener los patrones para almacenarlos en mysql. Pero como te dije, hay cosas que nunca he hecho con .Net porque no lo he necesitado y esto es lo más que puedo ayudarte.

  8. Dantors |

    hola

    Okas. bueno solo era una curiosidad…pense que era mas facil pero bueno tendremos practicar con otras aplicaciones, gracias por el comentario …

    Saludos…

  9. Macarena |

    hola Alex, primero que todo agradecer tus ganas de compartir tus conocimientos. te cuento estoy comenzando con el mundo .net y como trabajo en la universidad nos han dado una aplicacion donde he tenido un par dudas, el asunto es que tengo un proyecto web asp.net y estoy trabajando y la conecto con una BD mysql y lo que quiero es que por medio de esta aplicacion subir algunos archivos .txt a esta bd estoy usuando el fileupload de VS2005 pero aun no entiendo como funciona todos los post q he leido hablan de subirlas a un servidor y dan ejemplos y todo pero no entiendo como hacerlo para subirlos a mi DB me imagino que debe ser muy parecido a tu post aca. bueno mi pregunta es sabes como podria hacerlo????
    sabes como funciona este fileupload.. sabes de algun post q me pueda ayudar… de ante manos muchas gracias
    saludos….

  10. Alex |

    Aqui esta el link que te guia como utilizar el File Upload de VB.NET Solo que es info en ingles.
    Pero esta comprensible.
    http://www.developer.com/net/asp/article.php/3689276

    Saludos.

  11. Alex |

    Ah pero es para Mysql:
    http://www.daniweb.com/forums/thread46306.html#

  12. larturo |

    de donde puedo bajar tu proyecto te lo agradeceria

  13. Alex |

    Solo con copiar el código es suficiente para que obtengas el proyecto. este el todo el código de proyecto.

  14. Juan Carlos |

    oigan master de .net necesito una pequeña ayuda, necesito hacer un proyecto en visual basic .net 2005 con una conexion a mysql, ya tengo instalado el conector .net mysql y si puedo visualizar los datos arrastrando la tabla al form1 pero necesito programar botones como guardar, eliminar, actualizar con textbox por favor como puedo hacerlo se los agradecere infinitamente y de antemano gracias.
    cual quier eyuda agredeceria que me escribieran a mi correo porfavor suerte y cuidense.

  15. Juan Carlos |

    perdon mil disculpas ando un poco mal mi correo es jc_darien@hotmail.com

  16. Enrnes |

    Pues aqui esta el post para hacer eso :)

  17. andres |

    un favor ya pude guardar la imagen con este ejemplo , ahora quiero que me ayuden a mostrarla en un picture de vb .net

    gracias.

  18. Alex |

    En este ejemplo tambien dice como hacerlo.

  19. Manuel |

    Hola que tal, me eres de gran ayuda solo que tengo un problema con la aplicion no me manda ningun error solo que al ejecutarla seleccione la imagen y al guardarla me manda el mensaje de “Imagen no se guardo” nose a que se deba esto o que estoy haciendo mal

  20. andres |

    alex lo que pasa es que yo puse en el codigo Dim res As String = UpdateLogo(”UPDATE datosgenerales SET logo_img=?imagen WHERE id=’1′”, Img) y este solo me actualiza la imagen
    y yo quiero es que me inserte imagenes pero que no la actualice.

    escribi de esta manera y me dice imagen no guardada
    Dim res As String = UpdateLogo(”insert into logo values (?imagen)”, Img)

  21. andres |

    alex el codigo del ejemplo actualiza y yo quiero es que me inserte, por favor coloque el pedasito de codigo para insertar ,el sql “insert int ……” pues yo nesecito insetar varias imagenes…. gracias por su ayuda

  22. andres |

    alex el codigo del ejemplo actualiza y yo quiero es que me inserte, por favor coloque el pedasito de codigo para insertar ,el sql “insert int ……” pues yo nesecito insetar varias imagenes…. gracias por su ayuda..

  23. Alex |

    Andres cambia la sentencia UPDATE por INSERT

    INSERT datosgenerales SET logo_img=?imagen WHERE id=’1′”, Img

  24. Alex |

    Manuel:
    Checate el tamaño de tu imagen que no sea demasiado grande.
    Haz la prueba con oitras imágenes…

  25. Manuel |

    ya solucione el problema solo era el tipo de dato con el habia definido el campo en la bd,incluso ya logre guardar varios registros y realizar consultas de las distintas imagenes que guarde, muchas gracias por todo. solo una pregunta cual es tamaño maximo(en pixeles ó kb) de una imagen que se recomienda guardar en la BD. yo lo quiero implementar en una bd que guarde la foto de los empleados de un negocio X
    ya mañana intentare realizar el royecto del datagrid. Saludos

  26. Alex |

    Manuel:
    El tamaño lo indica tu campo en el formulario.
    Sin embargo considera que imagenes demasiado grandes alentan el rendimiento de la base de datos sobre todo si es una BD remota.

    No creo que exista un tamaño recomendado, eso debe ser en base a tu rendimiento.

  27. Hugo |

    Alex muy buena informacion, como harias para obtener la imagen desde la camara web, con un boton tomar la foto y otro boton para guardar la foto en la base de datos., Saludos.

  28. Hugo |

    Alex disculpa me podrias ayudar con el codigo para hacer el inverso de este ejemplo, traer la info de la base de datos y convertirla a imagen y la muestre en un picture box, Gracias.

  29. Alex |

    proximamente pongo un ejemplo de como manipular la camara web.

    El ejemplo inverso de esto esta aqui mismo. Checate bien el código.

  30. Hugo |

    Alex muchas gracias, si el codigo esta ahi, ya puedo grabar y leer imagenes de mi BD MySQL.

  31. andres |

    alex gracias por el codigo ya pude solucionar el problema…
    ahora lo que necesito saber y pues si usted sabe es.. como guardar un video en un formato no muy pesado en mysql desde vb y llamarlo.. asi como hizo con
    las imagenes.

    gracias …
    si algo por favor me escribe al correo…

  32. andres a |

    alex gracias por el codigo ya pude solucionar el problema…
    ahora lo que necesito saber y pues si usted sabe es.. como guardar un video en un formato no muy pesado en mysql desde vb y llamarlo.. asi como hizo con
    las imagenes.

    gracias …
    si algo por favor me escribe al correo…

  33. Alex |

    Andres:
    Aplica la misma función que está en este post:

    http://www.mejoralex.com/almacenar-pdf-o-doc-en-mysql-con-vbnet

  34. homero |

    hola ese codigo es justo lo k necesitaba pero me marca error en eso Me.OpenFileDialog1.Title = “Seleccionar imágen”

    si me pudieras asesorar en eso

    gracias por el aporte

  35. Alex |

    Homero, probablemente sea porque no has agregado el control OpenFileDialog desde el cuadro de herramientas.
    Si no es así dime que error es el que te marca.

  36. homero |

    hola ota ves
    gracias por la ayuda si me faltaba agregar ese componente,
    resulta qu este ejemplo te actualiza sobre un registro existente osea ubdate where
    yo nesesito hacer un inser into
    sustitullo el ubdate po inser into
    pero no me guarda

    mi proyecto es el regidtro de un credencial tengo k ir registrando el nombre , id, los datos y la foto como un registro nuevo

    de antemano gracias por el aporte y la ayuda

  37. angel |

    Hola muchas gracias por el codigo!… una pregunta… de que tipo debe ser la columna id de la base de datos ? jeje

  38. Alex |

    de tipo “longblob”

  39. Alex |

    Homero: Como le comente a Andres:
    Cambia la sentencia UPDATE por INSERT

    INSERT datosgenerales SET logo_img=?imagen WHERE id=’1′”, Img

  40. william |

    alex disculpa mira como hago para que el id sea una variable?

    INSERT datosgenerales SET logo_img=?imagen WHERE id=’1′”

    te agradeceria mucho si me lo dijeras

  41. william |

    mira el select lo hago perfecto, pero con lo que respecta al update para nada, no sé como hacer variable el id para que me guarde donde yo quiera sin necesidad de ir al codigo

  42. william |

    ya no importa ya lo logré hacer pero me costo

Escribe un comentario