Guardar imagenes en PostgreSQL desde C# | DevTroce.com

Guardar imágenes en la Base de Datos desde C#

Enero 24, 2010. Por GeekZero. Categorizado en Bases de Datos, C# .Net, Lenguajes de Programación, PostgreSQL. 12 Comentarios. Leido 2.270 veces.

Esto que veremos como hacer, se aplica a cualquier base de datos que soporte el tipo de dato BLOB o equivalente, aunque el ejemplo estará centrado en un motor especifico, el PostgreSQL ya que es uno de los motores que mejor tiempo de respuesta ofrece al trabajar con imágenes, hablo una vez que tenemos más del millon de imagenes, esto que digo está basado en una prueba mía con SQL Server, MySQL y Oracle XE. Por eso podría la mejor opción si necesitamos almacenar muchas imágenes y luego tener la facilidad que buscarlas con rápidez.

En éste ejemplo lo insertaremos desde C# .Net, pero primeramente debe existir la tabla que almacenará la imagen, y su tipo de dato debe ser BLOB (Binary Long, o campo binario largo). Las imagénes necesitamos convertirlas al binario para almacenarlas, veremos como tomar una imagen que está en algún directorio y lo almacenamos, también incluye el método para volver a pasarla a imágen por si necesitamos volver a visualizarla, pero no lo implementaré hoy.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
using Npgsql;
using System;
using System.Data;
using System.Text;
using System.Drawing;
using System.IO;
 
class ConvertirImagen
{
	public static byte[] Image2Bytes(Image pImagen)
	{
		byte[] mImage = null;
		try
		{
			if (pImagen != null)
			{
				using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
				{
					pImagen.Save(ms, pImagen.RawFormat);
					mImage = ms.GetBuffer();
					ms.Close();
				}
			}
			else { mImage = null; }
		}
		catch (Exception ex)
		{
			throw (ex);
		}
		return mImage;
	 }
 
	public static Image Bytes2Image(byte[] bytes)
	{
		if (bytes == null) return null;
		using (MemoryStream ms = new MemoryStream(bytes))
		{
			Bitmap bm = null;
			try
			{
				bm = new Bitmap(ms);
			}
			catch (Exception ex)
			{
				throw (ex);
			}
			return bm;
		}
	}
}
 
private static void guardarFotosPostgres(string vServidor, string vBaseDatos,string vUsuario, string vPassword, string vPathFoto)
{
	//String para cadena de conexion
	StringBuilder sCadena = new StringBuilder("");
	//objeto conexion
	NpgsqlConnection Con;
 
	//construccion de la cadena para conectarse a postgres
	sCadena.Append("Host=;");
	sCadena.Append("Database=;");
	sCadena.Append("User ID=;");
	sCadena.Append("Password=;");
	sCadena.Append("Port=5432;");
	sCadena.Replace("", vServidor);
	sCadena.Replace("", vBaseDatos);
	sCadena.Replace("", vUsuario);
	sCadena.Replace("", vPassword);
 
	Con = new NpgsqlConnection(Convert.ToString(sCadena));
 
	using (NpgsqlCommand Comando = new NpgsqlCommand())
	{
		try
		{
			//abrir la conexion
			Con.Open();
 
			//convierto la imagen en binario (el tipo de dato en postgres debe ser blob)
			byte[] Blob = ConvertirImagen.Image2Bytes(Image.FromFile(String.Format("{0}\\nuestraimagen.jpg", vPathFoto)));
 
			//asigno valores a los atributos del command que invocara un Stored Procedure
			Comando.CommandType = CommandType.StoredProcedure;
			Comando.Connection = Con;
			Comando.CommandText = "public.SPGuardaImagen";
			Comando.Parameters.Add("pfichero", Blob);
 
			//ejecucion de la funcion sin retorno de valores
			Comando.ExecuteNonQuery();
 
		} //end try
		catch (Exception ex)
		{
			throw (ex);
		} //end catch
		finally
		{
			Con.Close();
			Con.Dispose();
		}//end finally
	}//end using comando
}//end guardarFotosPostgres

Articulos Relacionados:

Etiquetas: , ,

Comentario

12 Comentarios en “Guardar imágenes en la Base de Datos desde C#” Hasta el momento.

  1. Carlos E. Carmona Carlos E. Carmona COLOMBIA Internet Explorer Windows dice:

    Felicitaciones! Este tema es realmente interesante.

    Tengo una duda con el ejemplo, ¿Donde se encuentra el código del procedimiento almacenado que guarda la imagen en Postgres?

  2. GeekZero GeekZero PARAGUAY Google Chrome Windows dice:

    Es sencillo, no lo puse ya que estaba considerando se tiene una tabla con un campo de tipo bytea (en el cual ira tu imagen).
    El SP quedaria algo semejante a esto, ojala te sirva de inspiracion :)
    <pre lang="sql">
    CREATE OR REPLACE FUNCTION public.SPGuardaImagen
    (
    pfichero               bytea
    )
    RETURNS void AS
    $$
    begin
    insert into public.imagenes
    (fichero)
    values (pfichero);
    end
    $$
    LANGUAGE 'plpgsql'
    VOLATILE
    CALLED ON NULL INPUT
    SECURITY INVOKER
    COST 100;</pre>

  3. DiegoA DiegoA COLOMBIA Mozilla Firefox Windows dice:

    Buenas tardes,

    El anterior es un excelente ejemplo, traté de implementarlo pero me encuentro con un error al momento de insertar la imagen en el procedimiento de almacenamiento (En su caso SPGuardarImagen)

    El cual me dice:

    Error de sintaxis en o cerca de

    <<",#3434(7),0144437'9=82>

    Como si la variable Blob tipo byte[] enviada como parametro tuviera un formato inválido o le faltara un cambio.

  4. DiegoA DiegoA COLOMBIA Mozilla Firefox Windows dice:

    De antemano gracias por su atención.

  5. DiegoA DiegoA COLOMBIA Mozilla Firefox Windows dice:

    La función en C# a la cual aplique alguna modificación quedo así:<pre lang="csharp">

    private static void guardarFotosPostgres(string vServidor, string vBaseDatos,string vUsuario, string vPassword, string vPathFoto, string vnombrefoto)

    {

    StringBuilder sCadena = new StringBuilder("");

    NpgsqlConnection Con;

    Con = new NpgsqlConnection(Convert.ToString("Server=localhost; Port=5432; User Id=Usuario; Password=Contrasena; Database=Imagenes;");

    using (NpgsqlCommand Comando = new NpgsqlCommand())

    {

    try

    {

    Con.Open();

    byte[] Blob = ConvertirImagen.Image2Bytes(Image.FromFile(String.Format("{0}", vPathFoto)));

    Comando.CommandType = CommandType.StoredProcedure;

    Comando.Connection = Con;

    Comando.CommandText = "insertarimagen";

    Comando.Parameters.Add("imagenex", Blob);

    Comando.Parameters.Add("nombreimagen", vnombrefoto);

    Comando.ExecuteNonQuery();

    catch (Exception ex)

    {

    MessageBox.Show("Error en la funcion guardarFotosPostgres:
    " + ex.Message, "Cuidado", MessageBoxButtons.OK, MessageBoxIcon.Error);

    throw (ex);

    } //end catch

    finally

    {

    Con.Close();

    Con.Dispose();

    }//end finally

    }

    </pre>

    En la base de datos la función se encuentra así:

    <pre lang="plsql">

    CREATE OR REPLACE FUNCTION insertarimagen (imagenex bytea, nombreimagen TEXT) RETURNS VOID AS

    $BODY$

    BEGIN

    INSERT INTO imagen (imagen, nombre) VALUES (imagenex, nombreimagen);

    END;

    $BODY$

    LANGUAGE 'plpgsql' VOLATILE;

    </pre>

    Muchas Gracias por su atención (Espero se vea claro el código).

  6. GeekZero GeekZero Google Chrome Windows dice:

    DiegoA, replique tu ambiente hasta donde puedo, creando la tabla y la función tal cual lo posteaste, luego copie tu codigo c# y funcionó, solo tuve que cerrar la llave del try, cerrar un parentesis de la linea 5 y wola! funcionó.. el StringBuilder de la línea 3 esta en valde en este código, puedes quitarlo..

    Fijate si tus objetos estan en el schema public..Tambien prueba esto desde PGAdmin directamente

    <pre lang="plsql">select * from insertarimagen (null, 'c:/devtroce.jpg');</pre> deberia probar si funciona al menos tu funcion..

    • DiegoA DiegoA COLOMBIA Mozilla Firefox Windows dice:

      Buenos días, he llevado a cabo las correcciones del código, es decir, el parentesis de la lína 5:
      Con = new NpgsqlConnection(Convert.ToString(“Server=localhost; Port=5432; User Id=imagen; Password=imagen; Database=Imagenes;”/*sCadena*/));
      La llave del try y también probé la consulta:
      select * from insertarimagen (null, ‘c:/devtroce.jpg’);
      Y continuo con el error, aunque con la última consulta en el pgAdmin me surgen un par de preguntas. ¿La función envía la ruta de la imagen a la base de datos? ó ¿La función envía la variable tipo byte[]?
      Porque el error que aparece: < tiene en donde econtramos “\” son dos, como si fuese la ruta de la imagen mal formateada.

      Gracias por su atención y colaboración, espero mi ejemplo pueda funcionar.

  7. GeekZero GeekZero PARAGUAY Google Chrome Windows dice:

    Buen día, es cierto he colocado la barra normal en vez de la invertida, pero no intentaba guardar un imagen en tu tabla, solo una cadena de texto, si te fija el bytea quedaría en nulo, lo único que intentaba era probar si te funcionaba la funcion, te ejecuto desde el pgAdmin o lanzo excepción alguna? Lo que intento determinar es si el problema está en tu bd o en tu app.

    Fijate que la llave del método guardarFotosPostgres() tampoco está cerrado, te compila este código?

  8. GeekZero GeekZero PARAGUAY Google Chrome Windows dice:

    Te sugiero que crees un topic en el foro (es nuevito por eso casi nada tiene aun) pero es mas fácil allí seguir un post largo con código..

  9. DiegoA DiegoA COLOMBIA Mozilla Firefox Windows dice:

    Ok, lo que haré será crear un nuevo tema en el foro de PostgreSQL ya que el error que surge es de la base de datos.

  10. DiegoA DiegoA COLOMBIA Mozilla Firefox Windows dice:

    Buenas Tardes, luego de llevar a cabo varias pruebas encontramos que el la version 8.2 de PostgreSQL funciona la inserción de la imagen pero en la versión 8.4 arroja el error comentado anteriormente. Continuaré con la exploración para que todo funcione bien con la versión 8.4.

Escribenos tu Comentario

Sigue los comentarios por RSS, suscribete a los feeds del comentario.