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:
- Funciones en PostgreSQL
- Leer, Guardar, Eliminar Ficheros de texto con Java
- Ejecutar procedimiento almacenado desde Java (JDBC)
- Crear Reportes con Visual Basic .Net, PostgreSQL y Crystal Report
- Desplegar ASP.Net en Apache Tomcat sobre GNU/Linux y SQL Server
Etiquetas: Bases de Datos, C# .Net, PostgreSQL

en
en
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?
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>
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.
Hola DiegoA, para ayudarte puedes copiarnos la DDL de tu tabla y de tu funcion?
De antemano gracias por su atención.
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).
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..
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.
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?
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..
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.
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.