miércoles, 3 de marzo de 2010

[ASP.NET] - Guardar Imagen base de datos

 

Introducción


Este articulo tendrá por objetivo demostrar algunas técnicas de tratamiento de archivos cuando es necesario manipularlos para que el cliente desde una página web tenga acceso a ellos.

Entre las operaciones no solo se permitirá la descarga sino que además el cliente podrá subir documentos, y guardar estos en una base de datos.

 

Listar archivos en una carpeta del sitio


Para este trabajo se hará uso del control GridView el cual listara los archivos contenidos en la carpeta del sitio.

Debe remarcarse que siempre que se trabaje con archivos que son subidos o trabajados en el sitio deberá usarse carpetas que estén dentro de la estructura de dicho sitio, no es una buena practica usar rutas como ser c:\, o D:\temp, si el sitio no ha sido creado allí.

public partial class ListarImagenes : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            DirectoryInfo dirInfo = new DirectoryInfo(Server.MapPath("~/files"));
            FileInfo[] fileInfo = dirInfo.GetFiles("*.*", SearchOption.AllDirectories);

            GridView1.DataSource = fileInfo;
            GridView1.DataBind();
        }
    }

    protected void btnSubirArchivo_Click(object sender, EventArgs e)
    {
        if (FileUpload1.HasFile)
        {
            string fullPath = Path.Combine(Server.MapPath("~/files"), FileUpload1.FileName);
            FileUpload1.SaveAs(fullPath);
        }
    }

}

En el evento Page_Load puede observarse como se hace uso de la funcionalidad de System.IO para recuperar el listado de archivos que se encuentran en la carpeta de nombre “files”.

En este caso para poder recuperar el path físico se hace uso de Server.MapPath(), y se referencia la ruta mediante ~/ ya que al encontrarse la carpeta en un nivel distinto es necesario hace referencia desde el root del sitio, en este caso usar ../file también hubiera funcionado.

Al ejecutar la pagina ~/ListarArchivos/ListarImagenes.aspx, se visualizara un resultado como el siguiente:

Imagen1

La grilla toma los valores de las propiedades del objeto FileInfo, es por eso que se hace uso de nombres como Name o Length para mostrar la información de la tabla.

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" CellPadding="4"
    ForeColor="#333333" GridLines="None">
    <RowStyle BackColor="#EFF3FB" />
    <Columns>
        <asp:TemplateField HeaderText="Nombre Archivo">
            <ItemTemplate>
                <asp:HyperLink ID="nombre" runat="server" NavigateUrl='<%# Eval("Name", "~/files/{0}") %>'
                    Text='<%# Eval("Name") %>'>
                </asp:HyperLink>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:BoundField DataField="Length" HeaderText="Tamaño" />
        <asp:TemplateField HeaderText="Descargar">
            <ItemTemplate>
                <asp:HyperLink ID="descarga" runat="server" NavigateUrl='<%# Eval("Name", "~/ListarArchivos/Download.aspx?filename={0}") %>'>
                       <img src="../imagenes/download.gif" alt="" width="30px" height="30px" style="border-width:0px;" />
                </asp:HyperLink>
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
    <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
    <PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" />
    <SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" />
    <HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
    <EditRowStyle BackColor="#2461BF" />
    <AlternatingRowStyle BackColor="White" />
</asp:GridView>

Además debe diferenciarse entre los dos link visualizados en la grilla, ya que estos trabajan de distintas formas,

-el primero es un link ordinario que apunta directo al archivos en la carpeta,

-el segundo es un link que fuerza la descarga del archivo a la PC del usuario, para su pre-visualización o guardar en disco.

Es interesante analizar el segundo caso, para este se hace uso de una pagina adicional que recibe como parámetro por QueryString el nombre del archivos.

Esta pagina buscara este valor pasado por parámetro en la carpeta del sitio donde se alojan las imágenes, y mediante el uso del objeto Response pondrá el archivo como respuesta del cliente.

La pagina que realiza esta tareas, es ~/ListarArchivos/Download.aspx :

public partial class Download : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        string filename = Request.QueryString["filename"].ToString(); 

        Response.Clear();
        Response.AddHeader("content-disposition", string.Format("attachment;filename={0}", filename));

        switch (Path.GetExtension(filename).ToLower())
        {
            case ".jpg":
                Response.ContentType = "image/jpg";
                break;
            case ".gif":
                Response.ContentType = "image/gif";
                break;
            case ".png":
                Response.ContentType = "image/png";
                break;
        }

        

        Response.WriteFile(Server.MapPath(Path.Combine("~/files", filename)));

        Response.End();

    }
}

De esta pagina se detecta al tipo de archivo mediante la extensión, especificando el ContentType correcto, debe remarcarse que esta técnica no solo funcionaria con documentos de imágenes, si el en futuro es necesario adaptarlo para la descarga de otro tipo de archivos, solo será cuestión de agregar el soporte a nuevas extensiones en el switch.

 

Subir Imágenes a una Base de Datos


Subir una imagen que será persistida en un campo en una base de datos requerirá de algunas vueltas mas en el procesamiento del archivo que es subido al servidor.

Para esto se ha creado una clase que actuara a manera de Data Access y contendrá las consultas que inserten la información en la tabla.

Para guardar la información se hará uso del siguiente método

public static void GuardarImagen(string nombrearchivo, int length, byte[] imagen)
{
    using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["default"].ToString()))
    {
        conn.Open();

        string query = @"INSERT INTO Imagenes (nombre, length, imagen)
                         VALUES (@name, @length, @imagen)";
        
        SqlCommand cmd = new SqlCommand(query, conn);
        
        cmd.Parameters.AddWithValue("@name", nombrearchivo);
        cmd.Parameters.AddWithValue("@length", length);

        SqlParameter imageParam = cmd.Parameters.Add("@imagen", System.Data.SqlDbType.Image);
        imageParam.Value = imagen;

        cmd.ExecuteNonQuery();

    }

}

la pagina ~/GuardarImagen/SubirImagen.aspx  contiene un control FileUpload que seleccionara el archivo a subir en el cliente y mediante un botón se realizara la siguiente acción:

protected void btnGuardar_Click(object sender, EventArgs e)
{

    if (FileUpload1.HasFile)
    {
        using (BinaryReader reader = new BinaryReader(FileUpload1.PostedFile.InputStream))
        {
            byte[] image = reader.ReadBytes(FileUpload1.PostedFile.ContentLength);

            ImagenesDAL.GuardarImagen(FileUpload1.FileName, FileUpload1.PostedFile.ContentLength , image);
            
        }

        CargarListadImagenes();
    }
    

}

Como puede visualizarse en el código se toma la información proveniente del upload y se invoca al método creado en el paso previo para insertar el registro, a este método se le pasa la imagen como un array de byte.

 

Listar archivos desde la base de datos


Bien ahora toca el momento de mostrar la información que es subida en el paso previo, para ello nuevamente se dispone de un GridView que es cargada en el Page_Load

public partial class SubirImagen : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
            CargarListadImagenes(); 
    }

    

    private void CargarListadImagenes()
    {
        GridView1.DataSource = ImagenesDAL.GetImagenList();
        GridView1.DataBind(); 
    }

}

Lo interesante de este código esta en la línea 13, en donde nuevamente se hace uso de de un método provisto por la clase de acceso a datos.

public static List<Imagenes> GetImagenList()
{
    List<Imagenes> lista = new List<Imagenes>();

    using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["default"].ToString()))
    {
        conn.Open();

        string query = @"SELECT Id, Nombre, Length  
                            FROM Imagenes";

        SqlCommand cmd = new SqlCommand(query, conn);

        SqlDataReader reader = cmd.ExecuteReader();

        while (reader.Read())
        {
            Imagenes img = new Imagenes(
                                    Convert.ToInt32(reader["Id"]),
                                    Convert.ToString(reader["nombre"]),
                                    Convert.ToInt32(reader["length"]));
            lista.Add(img);
        }

    }

    return lista;

}

 

Este método tiene algo particular devuelve una lista de un tipo de nombre “Imagenes”, la cual resulta ser una clase custom creada para hacer mas simple trabajar con la información obtenida en la consulta.

public class Imagenes
{
    public Imagenes(int id, string nombre, int length)
    {
        this.Id = id;
        this.Nombre = nombre;
        this.Length = length;
    }
    public int Id { get; set; }
    public int Length { get; set; }
    public string Nombre { get; set; }

    public byte[] Imagen { get; set; }
}

El control de grilla hará uso de las propiedades de esta clase para mostrar la información

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" CellPadding="4"
    ForeColor="#333333" GridLines="None">
    <RowStyle BackColor="#EFF3FB" />
    <Columns>
        <asp:BoundField DataField="Nombre" HeaderText="Nombre Archivo" />
        <asp:BoundField DataField="Length" HeaderText="Tamaño" />
        <asp:TemplateField HeaderText="Descargar">
            <ItemTemplate>
                <asp:HyperLink ID="descarga" runat="server" NavigateUrl='<%# Eval("Id", "~/GuardarImagen/Download.aspx?id={0}") %>'>
                       <img src="../imagenes/download.gif" alt="" width="30px" height="30px" style="border-width:0px;" />
                </asp:HyperLink>
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
    <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
    <PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" />
    <SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" />
    <HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
    <EditRowStyle BackColor="#2461BF" />
    <AlternatingRowStyle BackColor="White" />
</asp:GridView>

 

En esta oportunidad hay un detalle a remarcar en cuanto a la descarga, o acceso a la imagen desde el sitio, existen dos formas de tratar el archivo

- por medio de una pagina que reciba el id del registro que contiene la imagen

- por medio de un hadler de asp.net

 

Descargar la imagen por medio de una pagina


En los tag que forman el GridView seguro se ha observado que el link de descarga apunta a una url : ~/GuardarImagen/Download.aspx?id={0}

este es el documento que tomara el id informado por QueryString, realizaría la consulta tomando el archivo de imagen y lo pondrá en el objeto Response listo para enviarlo al cliente.

public partial class Download : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        int id = Convert.ToInt32(Request.QueryString["id"]);

        Imagenes imagen = ImagenesDAL.GetImagenById(id);

        Response.Clear();
        Response.AddHeader("content-disposition", string.Format("attachment;filename={0}", imagen.Nombre));

        switch (Path.GetExtension(imagen.Nombre).ToLower())
        {
            case ".jpg":
                Response.ContentType = "image/jpg";
                break;
            case ".gif":
                Response.ContentType = "image/gif";
                break;
            case ".png":
                Response.ContentType = "image/png";
                break;
        }

        Response.BinaryWrite(imagen.Imagen);
        Response.End();

    }
}

Es interesante remarcar que aquí se hace uso de otro método de la clase de acceso a datos, en este caso para tomar solo la información de una imagen.

 

public static Imagenes GetImagenById(int Id)
{
    Imagenes img = null;

    using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["default"].ToString()))
    {
        conn.Open();

        string query = @"SELECT Id, Nombre, Length, Imagen
                        FROM Imagenes
                        WHERE Id = @id";

        SqlCommand cmd = new SqlCommand(query, conn);
        cmd.Parameters.AddWithValue("@id", Id);

        SqlDataReader reader = cmd.ExecuteReader();

        if (reader.Read())
        {
            img = new Imagenes(
                            Convert.ToInt32(reader["Id"]),
                            Convert.ToString(reader["nombre"]),
                            Convert.ToInt32(reader["length"]));

            img.Imagen = (byte[])reader["Imagen"];

        }

    }

    return img;

}

Descargar la imagen por medio de un handler


Si bien el código interno que usara el handler será igual al de la pagina, este requieres algunos comentarios.

El primero es que a modo de ejemplo el uso de handler se desarrollo en la pagina ~/GuardarImagen/ListarImagenes.aspx

Esta pagina posee una grilla en donde una de las columnas hay un control de imagen:

    <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" 
        CellPadding="4" ForeColor="#333333" GridLines="None">
    <RowStyle BackColor="#EFF3FB" />
    <Columns>
        <asp:BoundField HeaderText="Nombre" DataField="nombre"  />
        <asp:TemplateField HeaderText="Imagen">
            <ItemTemplate>
                <img alt="" src="<%# Eval("Id", "Image.ashx?id={0}") %>" width="200px" height="200px" />
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
    <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
    <PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" />
    <SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" />
    <HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
    <EditRowStyle BackColor="#2461BF" />
    <AlternatingRowStyle BackColor="White" />
</asp:GridView>

la línea importante es

<img alt="" src="<%# Eval("Id", "Image.ashx?id={0}") %>" width="200px" height="200px" />

en esta se hace uso de un nombre y extensión especifico, en realidad lo importante es la extensión, el nombre en este caso puede ser cualquier otro y seguiría funcionando.

La imagen en este caso esta utilizando un handler para cargar la imagen, el mismo esta en la clase: HttpImageHandler.cs

public class HttpImageHandler : IHttpHandler
{

    public void ProcessRequest(HttpContext context)
    {
        int id = Convert.ToInt32(context.Request.Params["id"]);

        Imagenes imagen = ImagenesDAL.GetImagenById(id);

        context.Response.Clear();
        context.Response.AddHeader("content-disposition", string.Format("attachment;filename={0}", imagen.Nombre));

        switch (Path.GetExtension(imagen.Nombre).ToLower())
        {
            case ".jpg":
                context.Response.ContentType = "image/jpg";
                break;
            case ".gif":
                context.Response.ContentType = "image/gif";
                break;
            case ".png":
                context.Response.ContentType = "image/png";
                break;
        }

        context.Response.BinaryWrite(imagen.Imagen);
        context.Response.End();
    }

    public bool IsReusable
    {
        get { return false; }
    }

}

Lo interesando te este código es que al igual que la pagina de descarga, se tiene acceso al objeto Reponse, solo que en esta oportunidad es a través de HttpContext.

Además debe tenerse en cuenta para que el handler funcione es necesario agregar una línea en el archivo web.config

en este debería agregarse:

<add verb="*" path="*.ashx" type="GuardarImagenBaseDatos.GuardarImagen.HttpImageHandler"/>

El atributo type debe incluir todo el namespace, mas el nombre de la clase, debe tenerse en cuenta que esto puede variar en cada desarrollo dependiendo de donde se ubique la clase del handler.

Aclaración


Para que el ejemplo funcione es necesario contar con Sql Server Express instalado en la PC donde se ejecute el código, y el servicio debe estar iniciado

[C#]
[VB.NET]

181 comentarios:

  1. Exelente articulo me sirvio mucho para guardar archivos en la BD cargandolos desde Fileupload, el unico inconveniente es que no esta la opcion para recuperar el archivo desde la BD.

    Gracias por el aporte

    ResponderEliminar
  2. hola nsperez

    que bueno que sea util el articulo

    bien te comento que esto que consultas este implementado, no se si has visto:

    ImagenesDAL.GetImagenById()

    alli uso esta linea:

    img.Imagen = (byte[])reader["Imagen"];

    la cual devuelve un array de byte que representa el binario de la imagen, pasar esto a un tipo Image si es que lo necesitas no es dificil

    podrias hacer:


    public Image byteArrayToImage(byte[] byteArrayIn)
    {
    MemoryStream ms = new MemoryStream(byteArrayIn);
    Image returnImage = Image.FromStream(ms);
    return returnImage;
    }

    despues este si quieres lo grabas como imagen al disco, aunque tambien el byte[] directo se podria haber guardado a disco si se queria.


    saludos

    ResponderEliminar
  3. Disculpa estoy tratando de abrir el ejemplo pero al ejecutarlo me sale un error que dice algo como esto :"No se puede abrir la base de datos 'C:\DOCUMENTS AND SETTINGS\LINARES\ESCRITORIO\[VB.NET]GUARDARIMAGENBASEDATOS\GUARDARIMAGENBASEDATOS\APP_DATA\ARCHIVOS.MDF' en la versión 655. Este servidor es compatible con la versión 611 y anteriores. No se admite esta ruta de actualización. No se puede abrir la nueva base de datos 'C:\DOCUMENTS AND SETTINGS\LINARES\ESCRITORIO\[VB.NET]GUARDARIMAGENBASEDATOS\GUARDARIMAGENBASEDATOS\APP_DATA\ARCHIVOS.MDF'. CREATE DATABASE cancelada. Error al intentar adjuntar una base de datos nombrada automáticamente para el archivo C:\Documents and Settings\Linares\Escritorio\[vb.net]GuardarImagenBaseDatos\GuardarImagenBaseDatos\App_Data\Archivos.mdf. Ya existe una base de datos con el mismo nombre, no se puede abrir el archivo especificado o se encuentra en un recurso compartido UNC.".
    En que version de sql esta hecho?? En 2008?? porque yo tengo instalada la 2005, alguna sugerencia para solucionar este problema ?? :(

    ResponderEliminar
  4. hola Edalo

    Asi es, el ejemplo fue creando usando Sql Server Express 2008.

    Se me ocurre que podrias probar attachando directamente la db al servicio de sql server, usando para esto el Sql Server Management Studio.
    Igual no estoy seguro si aqui detectara tambien la version con que fue creada la db, puede que sea mas permisivo, pero la verdad nunca lo probe, ya que hace tiempo deje de usar sql server 2005.

    Recuerda ademas, si lo anterior funciona, que debes cambiar el ConnectionString del web.config, para que se conecte al servicio de sql server, y no realice un attach dinamico de la db.


    saludos

    ResponderEliminar
  5. Hola mi estimado la verdad que esta muy bueno este articulo, no se si me puedes ayudar es que quiero subir unos archivos .doc y que se visualicen en una pagina asp.net vb pero no quiero que se descargen solo que se muestren asi como un visor de documentos, queria implementarlo con el xmldatasource pero me es mas complicado haber si me das una mano gracias.

    ResponderEliminar
  6. hola Fatima

    Se me ocurren algunas alternativas, pero todas implcian que el usuario que accede al sitio tenga office instalado en su equipo, ya que sera al asociacion del tipo de documento vinculado con el IE lo que proporciona al visualizacion

    - una alterntiva podria ser que lances un popup de una ventana usando window.open() desde javascript indicando en al url el archivo de word.
    Esto deberia mostrarlo en esa ventana.

    - la otra seria que uses un tag IFRAME de html para que dentro indiques el archivo de word que quieres visualizar

    El problema pasa porque no hay un control para la web (no al menos de libre uso, pago puede que exista) que permita al visualizacion de documentos, sino que es la asociacion de la extension .doc con la aplicacion de Office Word, la que posibilita dicha visualizacion.

    Si el usuario cambia la aplicacion por defecto para visializar el word puede que se vea integrado al IE con esta nueva aplicacion, o que pida la descarga del archivo.

    Bueno espero sean de utilidad estos consejos
    saludos

    ResponderEliminar
  7. Hola Leandro, me sería muy util si pudieras aumentar al ejemplo, una columna tipo imagen al gridview en GuardarImagen.SubirImagen.aspx y mostrar la imagen que se acaba de subir a la BD y todas las existentes y lo mismo en ListarArchivos.ListarImagenes.aspx que si no me equivoco, es cuando se usa la tecnica de subir imagenes a un directorio.
    Saludos

    ResponderEliminar
  8. hola Richof

    Disculpa la tardanza en la repuesta

    Viendo el tema no creo haber entendido del todo cual seria el cambio, o ampliacion, del ejemplo

    Ya que no aplique ninguna tecnica para determinar cuales imagenes son rcientes y cuales no como para diferenciarlas.

    El ejemplo basicamente sube una imagen al servidor y luego la lista, pero no la marca como nueva, para diferenciarla del resto

    saludos

    ResponderEliminar
  9. Leandro, buenas tardes,
    Tengo una duda el código que se agrega en el web.config depende de que? pues es que no entiendo la ruta imagenes.guardarimagen.httphandler ?
    Gracias

    ResponderEliminar
  10. Ya sé a que se refiere al namespace seguido del nombre de la clase.

    Lo estoy haciendo igual pero me sale este error Línea 69:

    La clase se llama Thumbnail y el archivo se llama imagen.aspx
    Afecta en algo?

    Gracias

    ResponderEliminar
  11. EL ERROR ES ESTE
    Línea 69:
    add verb="*" path="*.ashx" type="Coldetec.Thumbnail"

    ResponderEliminar
  12. que pena este
    : No se pudo cargar el tipo 'Coldetec.Thumbnail'.

    ResponderEliminar
  13. hola Yeison

    Recuerda que cuando armes el type este debe incluir el nombre completo de la clase.

    Para esto revisa la parte del Assembly Name imagen
    para validar que ese sea el nombre completo, como veras en el ejemplo es algo mas largo del que has usado, por ahi falto algun namespace.

    saludos

    ResponderEliminar
  14. Hola Leandro. Me interesa mucho este artículo, y en este momento estoy enfrentado a un inconveniente.
    Deseo implementar un handler para mostrar thumbnails en una columna de un gridview.
    Ya tengo las imágenes correctamente cargadas, algo que comprobe al cargar alguna en un PictureBox.
    Todas las imágenes están en una tabla que además guarda otros datos de estos thumbnails que son fotos de autos: cada auto tiene su id, modelo, año, fabricante, etc.
    Hago la consulta, y el bind en la grilla, mostrándose los datos mencionados.
    Me está faltando mostrar las imágenes en su respectiva columna, a las que identifico por el id.
    Si yo ya tengo cargado un datatable con toda la info, ¿cómo puedo evitar una nueva consulta dentro del Handler?
    Es decir, al handler le paso el id por query. ¿Qué tendría que hacer? ¿Guardar el datatable en una sesión, y acceder por Item?
    O es inevitable que haga otra consulta dentro del handler, reabriendo una conexión que ya está abierta (con la que cargo el datatable mencionado)
    Muchas gracias por tu tiempo.

    ResponderEliminar
  15. hola fixertool

    Podrias dentro de handler realziar solo una vez la consulta a la db y guardar los registros en Session para que en sucesivos accesos no tengas que realzia el query nuevamente, sino que lo recuperas directo del DataSet (o DataTable)

    Dentro del Handler seguro necesites usa el context.Session
    para poder dejar el datatabel alli, en los siguientes acceso deberias preguntar si la Session tiene o no datos, sino los tienes entonces lanzas la query.

    if(context.Session["datos"] == null){
    //aqui realzias la consulta y cargas el datatable
    context.Session["datos"] = dt;
    }
    //aqui tomas la imagen del datatable

    Para acceder a un registro del datatable por ahi necesites el

    DataTable.Select (Método) (String)

    En tu caso filtrando por el id que proporcionas en el handler.

    saludos

    ResponderEliminar
  16. Gracias por tu respuesta. Al final logré recuperar los thumbnails de la base de datos y mostrarlos en la grilla, en los rows correspondientes según id. Más tarde optimizaré según tu sugerencia.
    Me pregunto si habiendo recuperado de esta forma las imágenes (thumbnails), podré mostrar mediante click en el thumbnail, y usando lightbox, las imágenes en tamaño grande. A estas imágenes también las tengo guardadas en la misma tabla, asociadas mediante id.

    ResponderEliminar
  17. hola Fabin

    Me alegro que hayas podido visualizar las imagenes.

    La verdad no he aplicado esta tecnica junto al lightbox, pero imagino que no deberia haber problema ya que en definitiva lo que se recibe es la imagen en el cliente y llega de la misma forma que al solicitar un archivo, o sea un array de byte, solo que con el handler uno tiene el control de los byte enviados, al invocar un archivo de imagen este se envia sin intervencion alguna al cliente.

    Por ahi esto resulte util para tu aplciacion:
    Visual jQuery LightBox

    saludos

    ResponderEliminar
  18. Me gusto mucho esta aplicacion de Guardar imagen base de datos, me gustaria publicara alguna aplicacion donde se manejen videos desde una base de datos access en windows form en c#; Se lo agradeceria mucho.

    ResponderEliminar
  19. hola maestro

    Videos desde una db Access, lo veo algo poco performante, no creo que Access como base de datos este preparada para soportar video.

    Si bien Sql Server podria alojar este tipo de archivos, creo que tampoco seria una buena opcion, ya que los videos de por si requieren una reproduccion un tanto especial, mas si hablamos de videos de varios megas.

    Habria que pensar en alguna tecnica que envie streaming

    Streaming

    saludos

    ResponderEliminar
  20. Todo anda bien (muestra imágenes desde la BD, anda bien el lightbox) Pero se me presenta un detalle. La columna de imagen está definida de forma parecida a tu anteúltima imagen de código, con dos diferencias: el tag img está embebido en un anchor, para poder relacionarla con el handler (y el lightbox adicional) que retorna la imagen full size.

    Y la otra es que al final decidí cargar una imagen genérica, en lugar de los thumbnails asociados al registro, por razones de performance (para aclarar, pongamos que puse una imagen que dice "haga click aquí").
    Pero no todos los registros tienen imagen asociada. En ese caso, quiero que se vea otra imagen, que advierta de que no hay imagen full size disponible. Y, sobre todo, que quede deshabilitado el anchor para que no se dispare el lightbox. O en caso de que no lo hubiera, para que no siga un enlace que de hecho no retornaría nada.
    Tricky, Huh? ¿Cómo se puede manejar esta situación?

    ResponderEliminar
  21. hola Fabian

    En este caso creo que el tema lo resuelves directo desde los datos cuando bindeas el control que arma el thumbnails, no se si sera un gridview, o algun otro.

    La idea es que de alguna forma en la query que usas para cargar la lista de imagenes puedas enviar un campo que indique si ese registro tiene o no imagen asociada, entocnes en el <# Bind> o en el RowDatabound, apliques la logica que valide ese campo y mostrar el link a una image o a otra, en realidad lo ideal seria que deshabilites la url o el link, sino hay imagen, para que no se pueda pulsar.

    Pera la idea es que por medio de un left join entres las tablas puedas unir la entidad con la imagen y enviar un valor qeu indique si hay imagen

    SELECT P.id, P.producto, COUNT(I.Id) as CantImagenes
    FROM Productos P LEFT JOIN Imagenes I
    ON P.Id = I.Id
    GROUP BY P.id, P.producto

    Si la cantidad de imagenes devuelve un valor mayor a cero entonces tiene y por lo tanto muestras el link

    Tambien podrias probar algo como esto

    SELECT P.id, P.producto, IIf(COUNT(I.Id) > 0, 1, 0) as CantImagenes
    FROM Productos P LEFT JOIN Imagenes I
    ON P.Id = I.Id
    GROUP BY P.id, P.producto

    Para que solo devuelva cero o uno si hay o no imagen.

    saludos

    ResponderEliminar
  22. Agradezco mucho tu respuesta. Te comento como lo resolví. No fue necesario el left join, ya que uno de los campos de la tabla me indicaba si había sido cargada la imagen. Y aunque no lo hubiera, me alcanzaba con preguntar si el campo de tipo imagen estaba en NULL.
    En cuanto a lo otro, lo solucioné con el evento RowDataBound del gridview.
    Si bien muestro una imagen de advertencia para cuando no hay archivo de imagen asociado al registro, no pude deshabilitar el link. Eso no me preocupa, ya que si el usuario igual hace click, al abrir el lightbox se verá esa misma imagen de advertencia.
    Pongamos que en lugar de lightbox hubiese redirigido a otra página, entonces habría mostrado los datos, y punto.
    Muchas gracias por tu tiempo.

    ResponderEliminar
  23. Hola Leandro muy buenio el ejemplo, mira que quiero saber que tipo de dato es el campo Imagen en la base de datos, pero no he podido verla... no se si tengas el script o me puedas ayudar con eso

    Grcias

    ResponderEliminar
  24. hola julito

    La imagen se persiste en un campo del tipo "Image" en la tabla

    Aunque si usas uno del tipo varbinary(MAX) tambien es valido

    Data Types (Transact-SQL)

    saludos

    ResponderEliminar
  25. Hola Leandro:
    "public Image byteArrayToImage(byte[] byteArrayIn)
    {
    MemoryStream ms = new MemoryStream(byteArrayIn);
    Image returnImage = Image.FromStream(ms);
    return returnImage;
    }

    despues este si quieres lo grabas como imagen al disco, aunque tambien el byte[] directo se podria haber guardado a disco si se queria."

    Como hago para grabar la imagen a disco? Necesito guardarla a disco para luego poder mostrarla en un control Image1.ImageURL
    Gracias

    ResponderEliminar
  26. hola Marcos

    Disculpa la demora de la respuesta

    Para grabar a disco lo asm simple es usa la funcionalidad de

    File.WriteAllBytes (Método)

    En este metodo indicas la ruta completa del archivo que quieres crear, y el array de byte directo (el que representa la imagen), no hace falta que lo conviertas a Image

    saludos

    ResponderEliminar
  27. saludos caballero muy interesante su aporte podria publicar algo similar pero esta vez insertando pdf a mi BD y que estos puedan ser desplegados en mi aplicacion le agradeceria muchisimo si me diera una idea de como hacerlo
    gracias...

    ResponderEliminar
  28. hola ronny

    buena idea el fin de semana proximo me hago un rato y armo un ejemplo de esto que planteas,
    pero voy a realizarlo para archivos mas variados como ser word, pdf, excel, etc
    igual salvo la validacion de la extension la tecnica igual para cualquier archivo

    saludos

    ResponderEliminar
  29. hola ronny

    Mira publique el artículo que habia comentado, evalualo a ver si te es de utilidad

    [ASP.NET] Grabar Archivo en base de datos

    ResponderEliminar
  30. private void button1_Click(object sender, EventArgs e)
    {
    try
    {

    string Cedula, Nombres, Apellidos, Sucursal;DateTime Fecha = dateTimePicker1.Value.Date ;
    Cedula = textBox1.Text; Nombres = textBox2.Text; Apellidos = textBox3.Text; Sucursal = textBox4.Text;
    Image Imagn = pictureBox1.Image;
    SqlConnection cnx = new SqlConnection(@"Data Source=FABRIZIOSERVER1\SQLEXPRESS;Initial Catalog=Cliente;Integrated Security=True");
    SqlCommand cmd = new SqlCommand();
    cmd.Connection = cnx;
    cmd.Connection.Open();
    cmd.CommandText = "INSERT INTO Cliente VALUES (@Cedula,@Nombres,@Apellidos,@Sucursal,@Fecha,@Imagn)";
    cmd.Parameters.AddWithValue("@Cedula", Cedula);
    cmd.Parameters.AddWithValue("@Nombres", Nombres);
    cmd.Parameters.AddWithValue("@Apellidos",Apellidos);
    cmd.Parameters.AddWithValue("@Sucursal",Sucursal);
    cmd.Parameters.AddWithValue("@Fecha",Fecha);

    SqlParameter ImageParam = cmd.Parameters .Add ("@Imagn",System.Data.SqlDbType.Image);
    ImageParam.Value = Imagn;

    cmd.ExecuteNonQuery();
    cmd.Connection.Close();
    cmd.Parameters.Clear();
    MessageBox.Show("LOS DATOS FUERON REGISTRADOS CON EXITO " ,"LISTO");
    }
    catch (Exception Ex)
    {
    MessageBox.Show("ERROR " + Ex,"ADVERTENCIA");
    }

    }

    ResponderEliminar
  31. hola EFRAIN

    No respondi antes porque vi tu pregunta en el foro, asi que imagine que ya lo habias solucionado

    http://social.msdn.microsoft.com/Forums/es/vcses/thread/1ade8622-8711-4d31-a6f6-93d1fe1bfc0e


    saludos

    ResponderEliminar
  32. Hola Leandro, he estudiado tu código, la verdad es que es muy util sobre todo la parte de handler, por lo menos es en lo que ya estoy más pez.

    Estoy intentando poner una imagen directamente en un control image sin tener que grabar en un fichero en disco, pero no se como asignar el array de byte al control imagen.
    ¿Debo usar un handler para hacerlo?

    muchas gracias

    ResponderEliminar
  33. hola Ados

    Justamente para plantear ese tema cree recientemente un post que podria ayudarte

    [ASP.NET] GridView – Edición Empleados

    Veras alli como se hace uso del handler para asignar la imagen al control Image


    saludos

    ResponderEliminar
  34. Hola Leandro, podrías volver a subir el archivo? De un día a otro este y otros archivos han dejado de estar disponibles :(
    Gracias

    ResponderEliminar
  35. hola Edalo

    Si, es un tema con el skydrive, se ve que alguna actualizacion que hicieron invalido los links que habia puesto en el articulo.

    te dejo el link directo para que lo descargues de este hasta que actualice:

    https://skydrive.live.com/?cid=b30e32da2150df24&sc=documents&id=B30E32DA2150DF24!268

    saludos

    ResponderEliminar
  36. Muchas gracias Leandro, como siempre presto a ayudarnos.
    Saludos

    ResponderEliminar
  37. Buenas noches Leandro, no se si pudieses subir el script o indicarme solo cual es la estructura de la BD

    Gracias de antemano

    ResponderEliminar
  38. hola Antonio

    En realidad no agregue el script porque es solo una tabla

    te dejo el script que la crea

    CREATE TABLE [Imagenes](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [nombre] [varchar](50) NOT NULL,
    [length] [int] NOT NULL,
    [imagen] [image] NOT NULL,
    CONSTRAINT [PK_Imagenes] PRIMARY KEY CLUSTERED
    (
    [id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
    GO
    SET ANSI_PADDING OFF

    saludos

    ResponderEliminar
  39. Muchas gracias Leandro por tu pronta respuesta :D

    ResponderEliminar
  40. Excelente Post Mi Hermano, Fue De Gran Ayuda...

    Saludos Desde Colombia.

    ResponderEliminar
  41. Hola

    Tengo una duda, yo tengo la base de datos hecha en sql server, quiero que me deje descargar el archivo tipo image almacenado en una base de datos pero en vb.net me muestre las imagenes de acuerdo a dis parametros que le envio es decir, deme la imagen que pertenece al usuario X, del año Y, y del curso Z, que me muestre un link de descarga de la imagen , no se mucho de vb.net ojala me puedas colaborar

    ResponderEliminar
  42. hola x4v1er

    La tecnica a seguir es la misma, creas el hadler encargado de poner en el response el array de byte de la imagen que toma por parametro

    solo que en tu caso pasaras en la url 3 parametros, en lugar de solo el id

    en el codigo del handler deberias tomar de la url en el querystring los 3 valores que el llegan, hacer la consulta a tu tabla filtrrando por estos y recuperar el registro de la imagen, para luego ponerlo en el Response


    saludos

    ResponderEliminar
  43. Hola estoy haciendo un metodo en una clase c# en los cuales tengo unos datos `para guardar NOMBRE APELLIDO Y LA IMAGEN pero no se de que tipo poner LA IMAGEN es algo asi

    http://chopapp.com/#v0ujgwhq

    gracias por su ayuda

    ResponderEliminar
  44. quisiera saber de que tipo colocaria IMAGEN pasandola como un parametro..n este link esta el codigo. Es de una clase c# que estoy haciendo para usarla o llamarla en los winforms

    gracias



    http://chopapp.com/#v0ujgwhq

    ResponderEliminar
  45. hola Rafa

    En el parametro la imagen deberia ser del tipo byte array, o sea byte[]

    Si revisas el articulo veras que al usar la instruccion en la query es justamente de este tipo

    Recomendaria leas este otro articulo

    [WinForms] Edición Empleados – Grabar imagen en base de datos

    alli se muestra mucho mejor esto que comento

    saludos

    ResponderEliminar
  46. Buenas tardes Leandro, perdona que escriba mi comentario en este articulo que ya ha pasado un buen tiempo desde que se publico. Me gustaría saber si existe alguna forma de poder recuperar una imagen guardada en la forma que se explica en tu articulo, pero no guardarla en un directorio sino poder enviarla como archivo adjunto en un correo utilizando sp_send_dbmail de sql server. es decir adjuntar el archivo que de resultado un query.

    ResponderEliminar
  47. hola Ismael Montes

    La verdad nunca he usado el procedure sp_send_dbmail, pero si puedo ver en al documetacion

    sp_send_dbmail (Transact-SQL)

    que tiene un parametro para esto que necesitas
    @query_attachment_filename
    aunque veo que este lo que espera es un string con el path al archivo que se adjunta y no un array de byte

    quizas se deba bajar primero el byte[] a un archivo fisico antes de enviar el mail

    saludos

    ResponderEliminar
  48. hola oye no podiras mostrar una imagen de tus base de datos creadas

    ResponderEliminar
  49. hola amigo oye no podrian poner ña imagenes de tu base de datos para comprender un poco mejor te agradeseria mucho

    ResponderEliminar
  50. hola zenit

    el tema es que no hay mucho que mostrar la db solo tiene una tabla unica

    revisa la respuesta que le doy a Antonio, ahi puse el script que crea la unica tabla donde registra el ejemplo


    saludos

    ResponderEliminar
  51. Estimado tu blog me a servido de mucha ayuda, muchas gracias. Una consulta estoy trabajando con un FileUpload y quisiera que al momento de examinar me abriera una ruta en especial, como puedo hacer esto, llevo dias investigando y no encuentro nada satisfactorio, espero me puedas ayudar, gracias.

    ResponderEliminar
  52. hola Maximiliano

    El tema es que la carpeta que definirias por defecto pertence a la pc del usuario, por temas de seguridad este control no puede acceder a las carpetas ni definir una porque seria un riesgo, una vulnerabilidad

    ademas estas en un entorno web como podrias saber de forma global que todos los usaurio de todo el mundo que acceda a un sitio web tendra esa carpeta, no puede por eso no hay forma de definir una por defecto.

    Ademas habras visto que cuando selecionas un archivo, no puede acceder a su ruta desde el cliente ni desde el servidor, o sea el path completo tampoco lo puede recuperar

    En el cliente creo que la maximo es el nombre del archivo y desde el servidor solo llega el array de byte, justamente porque un ambiente web no puede acceder a las carpetas por si solo, requiere de una accion del usaurio, sino millones de virus estarina haciendo de las suyas

    saludos

    ResponderEliminar
  53. Estimado, me dejaste muy claro con el tema una vez mas gracias.

    ResponderEliminar
  54. Ola leandro tengo un problema: "No se puede abrir la base de datos 'C:\DOCUMENTS AND SETTINGS\LINARES\ESCRITORIO\[VB.NET]GUARDARIMAGENBASEDATOS\GUARDARIMAGENBASEDATOS\APP_DATA\ARCHIVOS.MDF' en la versión 655. Este servidor es compatible con la versión 611 y anteriores. No se admite esta ruta de actualización. No se puede abrir la nueva base de datos 'C:\DOCUMENTS AND SETTINGS\LINARES\ESCRITORIO\[VB.NET]GUARDARIMAGENBASEDATOS\GUARDARIMAGENBASEDATOS\APP_DATA\ARCHIVOS.MDF'. CREATE DATABASE cancelada. Error al intentar adjuntar una base de datos nombrada automáticamente para el archivo C:\Documents and Settings\Linares\Escritorio\[vb.net]GuardarImagenBaseDatos\GuardarImagenBaseDatos\App_Data\Archivos.mdf. Ya existe una base de datos con el mismo nombre, no se puede abrir el archivo especificado o se encuentra en un recurso compartido UNC.".
    y utilizo visual 2008. pero me puedes decir k tipo de valores tienen las columnas gracias

    ResponderEliminar
  55. ya solucine ese problema creando una nueva bd pero una pregunta en el campo Imagen k koloko la direccion de la imagen o k por k no e podido gracias

    ResponderEliminar
  56. muy util el codigo me haz salvado mi graduacion :D

    ResponderEliminar
  57. hola ross junior

    te comento que la db que uses para crear el articulo es SqlServer 2008 R2 Express

    quizas sino tienes esta version o una superior tengas problemas

    en el campo image deberias definirlo como "Image" o tambien deberias funcionar como varbinary(max)

    saludos

    ResponderEliminar
  58. Hola Leandro...fue de muy util tu ayuda

    ResponderEliminar
  59. Hola Leandro fue de muy util sobre como guardar una imagen en la base de datos.....

    ResponderEliminar
  60. y si kiero hacerlo desde el update panel?

    ResponderEliminar
  61. hola javier

    En principio deberia ser lo mismo, ya que el UpdatePanel lo que evita es el refresh de la pagian pero por detras las tecncias de asp.net se consevan

    si haces un upload de una imagen, quizas usea el
    AsyncFileUpload

    pero igual la forma en como grabas en la db y como recuperas la imagen no cambia en nada

    saludos

    ResponderEliminar
  62. Hola Leandro, sabes que tengo un handler que funciona bien, o sea lo abre en mi maquina local, cuando subo todo al server, deja de funcionar.

    El handler abre a su vez un PDF, en donde vamos completando los campos.

    Se te ocurre algo, para saber porque abre el handler en blanco en el server y no asi en la maquina local.

    Saludos
    Eduardo

    ResponderEliminar
  63. oiee. solo lo baje en c# y al abrirlo.. corre.. osea funciona.. pero no me guarda direcciones en a base da datos. PD no le he movido a nada masque al webconfig.. que cambié los datos por mis datos de logueo en sql.. tengo que crear una bd con tablas o algo asi? o se va insertando todo solo o como.. no entiendo :S

    ResponderEliminar
  64. bueno.. ya tengo la BD que se llama imagen y la tabla que introduje con el script que le dejaste a antonio. a que le tengo que mover para que inserte en mi bd. esta como default no?.. se conecta automaticamente.. pero como hace referencia a la BD.. se hace en el webconfig? esque nunca he echo conexiones a bd y por eso no se mucho del webconfig.. pero pues asi de simple como es la pregunta.. ¿que tengo que cambiar para que se inserte en mi BD? porfavor.. (: y gracias esta muy bueno el post

    ResponderEliminar
  65. hola DSInfo

    de casualidad en el handler defines algun try..catch que pudiera estar atrapando algun error que no se devuelve a la pagina ?

    quizas debas ver de agregar codigo de logeo en ese habdler para que registre en un archivo que sucede

    cuando dices que el handler abre te refires a que toma el pdf y lo envia en el response al cliente, o sea no es que lo ejecutas, porque si haces esto se abrira en el servidor, no en el cliente

    saludos

    ResponderEliminar
  66. hola p4co0

    exacto por medio del web.confign defines la cadena de conexion a la base de datos

    lo que debes cambiar para re-apuntar a la db que tu usas es la seccion de





    es alli donde debes modificar

    saludos

    ResponderEliminar
  67. Hola, sabes estoy iniciando la programacion en c# y estoy tenuendo problemas para grabar un documento tipo .tiff multipaginas a sql server, ya que al traerlo de nuevo solo veo la primera pagina, a ver si me ayudas, gracias

    ResponderEliminar
  68. hola Javier

    no entendi
    o sea cuando grabas envias al campo de la tabla un array de byte, por lo tanto recuperas lo mismo cuando tomas la info de ese campo

    por ahi en lugar de usar un tipo de dato image podrias suar un varbinary(max) para ver si el tipo de dato del campo no afecta la imagen, pero igual es raro

    saludos

    ResponderEliminar
  69. Hola Leandro, estoy trabajando en un proyecto el cual necesita mostrar las imagenes directamente en una grilla yo estoy intentando utilizar un gredview, sinceramente tu codigo me a resultado bastante util a la hora de guardar las imagenes como mapa de bits en una base de datos, pero todavia no e podido resolver el problema de que la gredview me muestre las imagenes, estube mirando bastante por internet y las soluciones son para winforms en su mayoria pero no muestran como listar imagenes desde una base de datos a un gredview. Trabajo con un sistema en 3 capas, Persistencia, Logica y Presentacion. My pregunta es; creo un Objeto que tiene Id, Nombre, Length e Imagen de tipo Image como aconsejas en el ejemplo, pero a la hora de mostrar este objeto en un gredview, muestra todos los datos menos la imagen que por sierto es en realidad lo que necesito mostrar. Agradeceria si me pudieras ayudar con este problema, gracias.

    ResponderEliminar
  70. hola Angel

    Porque crear una propiedad en tu objeto de tipo Image, eso no deberia ser asi, debes usar un byte[], la imagen es un array de byte
    El image solo se usa para cargar controles o trabajar con la imagen pero si es para enviarla por el Request es solo un array de byte

    public byte[] Imagen {get; set;}

    en un entorno web olvidate del Image

    saludos

    ResponderEliminar
  71. Hola Leandro muchas gracias por contestar tan rapido, te cuento que tome en cuenta tu ayuda, pero el problema persiste. Voy a intentar ser mas detallado, como te comente tengo un proyecto de 3 capas
    Clase Imagenes
    private int _id;
    private string _nombre;
    private int _length;
    private byte[] _imagen;

    public byte[] Imagen
    {
    get { return _imagen; }
    set {_imagen = value;}
    }

    public Imagenes(string pNombre, int pLength, byte[] pImagen)
    {
    _nombre = pNombre;
    _length = pLength;
    _imagen = pImagen;
    }

    public Imagenes(int pId, string pNombre, int pLength)
    {
    _id = pId;
    _nombre = pNombre;
    _length = pLength;
    }

    public override string ToString()
    {
    return (_id.ToString()
    + _nombre.Trim()
    + _length.ToString()
    + _imagen);
    }
    En logica llamo a la capa Persistencia:
    public static List ListarImagen()
    {
    List oResultado = PersistenciaImagenes.ListarImagen()
    return oResultado;
    }

    Y en persistencia me conecto con la BD para cargar un objeto de tipo Imagen (no incluyo la parte de conexion, ya comprobe que no es ese el problema)

    reader = oComando.ExecuteReader();
    while (reader.Read())
    {
    Imagenes oFoto = new Imagenes( Convert.ToInt32(reader["Id"]),
    Convert.ToString(reader["nombre"]),
    Convert.ToInt32(reader["length"]));
    oFoto.Imagen = byte[])reader["Imagen"];
    oResultado.Add(oFoto);
    }
    return oResultado;

    Te cuento que segui con F11 paso a paso y logro traer todos los datos desde la BD pero al momento de mostrar me los muestra todos menos la imagen.

    el gredview lo cargo asi:
    GridView1.DataSource = LogicaImagenes.ListarImagen();
    GridView1.DataBind();

    Te pido disculpas por haber sido tan extenso y desde ya te agradezco cualquier sugerencia que me pueda ayudar a resolver el problema. Muchas Gracias

    ResponderEliminar
  72. hola

    la definicion de la entidad y la carga desde la persistencia parecen estar correctos, pero el tema es como usas este codigo desde el handler?

    analiza el codigo de este articulo y veras que al control Image de asp.net no le asignas el byte[] de forma directa, sino que este lo envias en el Response, por eso el handler

    Eso es lo que deberias validar junto al ContentType que definas con el tipo de imagen que envias

    saludos

    ResponderEliminar
  73. Hola Leandro, la verdad muchas gracias, tenias razon me faltaba agregar estas lineas de codigo al webb config:

    httpHandlers
    add verb="*" path="*.ashx" type="Persistencia.HttpImageHandler
    httpHandlers

    Con eso pude listar las imagenes en el gredview sin problemas.
    Otra vez, Muchas Gracias por la ayuda y por la atencion.
    Gracias Saludos

    ResponderEliminar
  74. Gusto en saludarte nuevamente Leandro, espero me puedas ayudar con los siguiente: Se me presenta la oportunidad de resolver un problema con una aplicación que cargar archivos (como maxímo de 3MB) dentro de determinada carpeta en el servidor con el FileUpload, pero los usuarios tienen una conexión lenta a internet y el timeout les corta la subida de los archivos, las preguntas son, ¿Subir los archivos por FTP es buena opción?,¿Cuál consideras que sea la mejor opción para cargar archivos sin importar el tamaño y la velocidad de internet de los usuarios?.

    Muchas gracias de antemano.
    Ernesto

    ResponderEliminar
  75. Hola Leandro como vas, tengo una consulta sobre la carga de archivo. Antes que nada te tengo que agradecer el postear este articulo que ufff, es de una gran

    ayuda para muchos.
    Bueno, te comento mi incidente, lo que estoy realizando es la carga de archivos a una tabla de mi BD, el codigo realiza la carga muy bien, pero con archivos

    de muy reducido tamaño (tamaños de menos de 1MB); para ello he investigado un poco y me llevo a aumentar algunas configuraciones tanto en el web.config del

    servicio como en el web.config del cliente, mira lo que tengo en ambos:

    -- web.config servicio








    -- web.config cliente















    Pero sabes, aun no me permite cargar archivos de grande tamaño. Me puedes ayudar a identificar este inconveniente y el cual me dice que es una Excepcion en

    la Comunicacion. De hecho el mensaje de error que me manda es: The remote server returned an error: (400) Bad Request.

    Ah, otro detalle que no queria pasar por alto es que la carga permite cualquier tipo de archivos.

    Te lo agradezco mucho Leandro.

    ResponderEliminar
  76. hola Alondra

    algo que me llamo la atencion es porque mencionas dos web.config en la explciacion

    se supone que la pagina donde realzias el upload de la imagen es una sola, y no hay un cliente que actualziar porque el cliente seria el browser del usuario y eso no se configura
    solo el server con el iis que aloja el sitio es quien se define los valores de tamaño permitido en la subida, que ademas si es menos de 1Mb no deberias tener problemas con la configuracion por defecto que permite archivos de hasta 4Mb

    o es que el sitio web se comunica con un web service ? porque ojo la forma en que pasas info a un servicio puede ser distinta a usar el fileupload

    saludos

    ResponderEliminar
  77. Hola Leandro, segun he estado analizando el caso, sera que en la capa de transporte la comunicacion este algo muy por debajo para permitir la carga de archivos de mas de 1mb? Tenes alguna solucion para dicha modificacion o algun comentario que me ayude.

    Gracias y totales gracias

    ResponderEliminar
  78. hola Alondra

    no veo porque un archivo de menos de un mega no puedas subirse por medio del fileupload al servidor

    si se que hay un limite al tamaño maximo de archivo, que esta definido por defecto en 4Mb, pero el tamaño minimo no hay restriccion

    no sera un problema en la logica del codigo que generas? o sea cuando subes el archivo no llega el array del byte al servicor? y realizas el SaveAs de este a un archivo

    saludos

    ResponderEliminar
  79. Buenas tardes Leandro,

    Primero quiero agradecer por este gran aporte, me ha sido muy útil pero no he podido llegar a lo que quiero.

    Mi caso es el siguiente he hecho una galeria de imagenes en JQuery y quiero generar las imagenes dinamicamente. Las imagenes las traigo de la BD y vienen en Bytes[].

    Estoy trabajando asp.net con C#

    En el load del formulario uso un ciclo for de acuerdo a la cantidad de imagenes en la BD. Dentro de este for uso una clase .ashx para generar la url de la imagen (string url="GetImage.ashx") que la muestro mediante this.UnDiv.InnerHTML

    El problema es que me muestra en la galeria solo la ultima imagen de todas las que estan en la BD. Haciendo un paso a paso logro evidenciar que el recorrido del for se hace de manera correcta, pero solo esta yendo una vez a la clase .ashx

    Por favor si puedes ayudarme te agradecería. Saludos

    ResponderEliminar
  80. Bueno ya he solucionado mi problema y era en la forma con la que obtenía el valor de un parámetro en la clase .ashx

    Lo hacia mediante una variable global creada en el Web.confing. ahora recibo el parámetro enviándola por post string url = "GetImage.ashx?id=Valor" y en mi clase lo obtengo de esta manera doc = context.Request.Params["doc"].ToString();

    Gracias de todos modos :D Saludos

    ResponderEliminar
  81. hola LeinerB

    si usas jquery, porque estas usando
    this.UnDiv.InnerHTML

    porque no lo haces con jquery, usando el selector
    $('#iddiv').html(aqui html);

    puedes insertar codigo html

    saludos

    ResponderEliminar
  82. Hola Leandro, te adjunto la parte del codigo donde realizo la carga, no le veo nada extraño si.

    Muchas gracias de antemano.

    public void Guardar()
    {
    foreach (UploadedFile file in RadAsyncUpload1.UploadedFiles)
    {
    byte[] bytes = new byte[file.ContentLength];
    file.InputStream.Read(bytes, 0, file.ContentLength);
    DocumentoSoporteSContractClient connection = new DocumentoSoporteSContractClient("basicEndPoint");
    try
    {
    DocumentoSoporteInsertarRQ command = new DocumentoSoporteInsertarRQ();
    command.DocSoporteInRQ = new DocumentoSoporteDContract(); //datacontract

    command.DocSoporteInRQ.TipoDeDocumento = file.GetName();
    command.DocSoporteInRQ.Documento = new Binary { Bytes = bytes };
    command.DocSoporteInRQ.CreadoPor = (Page as SIFPage).SecurityInfo.SIFUser.SIFUserId; ;
    command.DocSoporteInRQ.FechaCreacion = System.DateTime.Now;

    connection.DocumentoSoporteInsertar(command.DocSoporteInRQ); //se manda a guardar
    Mensaje.Show("carga satisfactoria")
    }
    catch
    {
    thrown;
    }
    }
    }

    ResponderEliminar
  83. hola Alondra

    la verdad desconozco algunas funcionalidades de ese codigo

    - nunca use un RadAsyncUpload1, imagino es un control de telerik para subir archivos multiples, quiero pensar que eso funciona

    - pero lo que si nunca usea es DocumentoSoporteSContractClient
    imagino por el nombre que es algo de sharepoint, pero la verdad no tengo idea de como se usa

    saludos

    ResponderEliminar
  84. Hola yo estoy haciendo un sitio web en el cual en la pagina elijo una imagen para subirla entonces el nombre de la imagen lo guardo en un hidden field.
    Y entonces al guardar en la BD quiero que se muestre la ruta.
    Bueno mi problema es que el fileupload va vacio en la propiedad FileName.

    ResponderEliminar
  85. hola lucia rosas

    el tema es que al poner la ruta en un hidden no estas haciendo un upload de la imagen solo defines una ruta de una imagen que esta en el cliente, pero nunca haces el upload en si solo llevas un string con el nombre del archivo y solo eso

    debes dejar seleccionado el archivo en el fileupload para que se pueda realizar la subida del byte[] al sitio web, usar un hidden no funciona

    saludos

    ResponderEliminar
  86. hola leandro felicitarte por un excelente articulo y super entendible, algo puntual cuando creaba el handler me salia un error aqui;
    public class HttpImageHandler:IHttpHandler
    Indicandome que el miembro isrehusable no estaba creado para lo cual el vs me lo solucion agregando esto:
    #region Miembros de IHttpHandler

    public bool IsReusable
    {
    get { return false; }
    }

    #endregion
    lo cual en el return determinaba una excepcion lo cula quite y expuse tu conocimiento de return false y vacan dio de maravillas, por si acaso alguno tenia dicho problema, un saludo cordial leandro y esperamos muchos articulos igual, adios.

    ResponderEliminar
  87. Bueno yo le hice de esta forma.. espero que alguien le sirva.. en la forma como lo hice le borro el nombre a la foto y le agrego un código asi limito el tamaño de letra que pueda tener la foto.. solo tomo la extensión de la imagen ante de subirla..

    string oFotos = "";
    string sExt = "";
    string oError = "";

    try
    {

    Random r = new Random();
    int numeros = r.Next(10000000, 99999999);

    oFotos = Path.GetFileName(imgSubida.PostedFile.FileName);
    sExt = Path.GetExtension(oFotos);
    oFotos = oFotos.Substring(oFotos.LastIndexOf(".") + 1).ToLower();
    oFotos = DateTime.Now.ToString("yyyyMMdd_hhmmss") + "_" + numeros + sExt;
    if (oFotos.Equals(""))
    {
    oError += "Selecciones una imagen
    ";

    }
    else if (!ValidaExtension(sExt))
    {
    oError += "Solo es permitido imagenes con las extensiones jpg, png
    ";


    }
    else if (imgSubida.HasFile)
    {

    imgSubida.PostedFile.SaveAs(Server.MapPath("~/imagenes") + "\\" + oFotos);


    }



    }
    catch
    {
    oError += "Selecciones una imagenes con las extensiones jpg, png
    ";
    }
    if (oError != "")
    {

    lblError.Text = oError;
    }else
    {
    aca ingresa a la base de datos.
    }


    private bool ValidaExtension(string sExt)
    {
    Boolean rel = false;
    switch (sExt)
    {
    case ".jpg":
    case ".jpeg":
    case ".png":
    case ".gif":
    case ".bmp":
    rel = true;
    break;
    default:
    rel = false;
    break;

    }
    return rel;
    }

    ResponderEliminar
  88. Hola Leandro, podrias ayudarme con algo, quisiera listar los archivos en una sola celda, al dar clic sobre el archivo que debe estar separado por los demas, se debe permitir descargar, gracias espero su respuesta

    ResponderEliminar
  89. hola Johanna

    no entendi, como es eso de una sola celda? o sea si usas un gridview se supone que tienes una fila y columna para cargar los datos

    o estas pensando en usar otro tipo de control? y no el gridview, como se usa en el articulo

    saludos

    ResponderEliminar
  90. Mira, tengo una tabla formada por 4 campos: fecha, usuario, descripcion, archivos.
    Los usuarios si tienen algún requerimiento, describen su requerimiento y pueden adjuntar mas de un archivo.
    Yo guardo los archivos adjuntos en una ruta del servidor, la cosa es que al poner todos los datos en el gridview como consulta, desearia se vieran los nombres de los archivos que ha adjuntado cada cliente,osea, esto deberia verse en la columna archivos, al dar clic en el nombre del archivo se descargue..

    :( . Hice algo con hyperlink pero los nombres del los archivos se ven como que si todos fueran un solo link.. Y yo deseo que cada nombre se vea como link

    ResponderEliminar
  91. hola Johanna

    has validado como defines el link dentro del ItemTemplate del gridview ?

    porque por lo que comentas parece ser un problema con el template
    aunque no me queda claro que es lo que aparece como un link, porque si defines el hiperlink en una columna del grid solo deberias aplicarse a esa columna

    saludos

    ResponderEliminar
  92. Hola leandro, Estoy trabajando con tu articulo de este blogg sobre el UploadFile,, esotoy trabajandor en Visual Studio 2010 ,, pero tengo unn problema,, Cuando elijo el archivo que quiero subir , al momento de querer cargarlo primero valida si el file upload tiene un archivo cargado asi:
    if (FileUpload1.HasFile)
    {
    string fullPath = Path.Combine(Server.MapPath("~/files"), FileUpload1.FileName);
    FileUpload1.SaveAs(fullPath);
    }
    }
    pero el FileUpload1.HasFile siempre me da falso ,, apesar de que ya elegi la imagen que quiero subir y no se por que,ya comprobe y en efecto no aperece informacion del archivo ,, plis help me¡¡¡¡

    ResponderEliminar
  93. hola alex

    la verdad no sabria decirte que podra esta pasando

    de casualidad usas el UpdatePanel ? porque se que hay problemas con el fileupload cuando estas con este integrado


    saludos

    ResponderEliminar
  94. Si leandro que crees? ya solucione el problemita,, y si es por el UpdatePanel ,, mi solucion fue Integrar el AsyncFileUploadExtender ,, muchas gracias ... muy buen tutorial

    ResponderEliminar
  95. buenas
    saludos espero tu ayuda soy nuevo en esto. estoy elaborando un proyecto en visual webdeveloper
    tengo una base de datos creada que llame imagen para guardar las imagenes del proyecto y recionarlas con los usuarios.
    el problema estas cuando intento gurdar las la imagen en la base de datos,segui el articulo pero me da errol,no si creaste una cadena de conexion en el web.config o algo asi,si la creaste me puedes enviar los datos de como las crearte y sus parametros, yo cree una pero las imagen no se guardan en la base de datos,si en la carpeta fotos de mi proyecto,te envio el codigo que uso para la cadena de conexion







    este es metodo que utilisas para guardar la imagen podificado

    public static void GuardarImagen(string nombrearchivo, int length, byte[] imagen)
    {
    using (SqlConnection conn = newSqlConnection(ConfigurationManager.ConnectionStrings["conn"].ToString()))
    {
    conn.Open();
    string query = @"INSERT INTO Imagene (, imagen)
    VALUES @imagen)";

    SqlCommand cmd = new SqlCommand(query, conn);
    SqlParameter imageParam = cmd.Parameters.Add("@imagen", System.Data.SqlDbType.Image);
    imageParam.Value = imagen;
    cmd.ExecuteNonQuery();
    }

    }

    con este codigo cargo la imagen a las carpeta foto de mi proyecto

    protected void Button1_Click(object sender, EventArgs e)
    {
    if (FileUpload1.HasFile)
    try
    {
    FileUpload1.SaveAs(Server.MapPath("~/fotos" + FileUpload1.FileName));
    Label1.Text = "File name: " +
    FileUpload1.PostedFile.FileName + "
    " +
    FileUpload1.PostedFile.ContentLength + " kb
    " +
    "Content type:" +
    FileUpload1.PostedFile.ContentType;
    }
    catch (Exception ex)
    {
    Label1.Text = "ERROR: "+ ex.Message.ToString();
    }
    else
    {
    Label1.Text = "You have not specified a file or the file has not been found.";
    }
    }

    esto otro que pones en tu articulo para cuardar la imagen
    protected void btnGuardar_Click(object sender, EventArgs e)
    {
    if (FileUpload1.HasFile)
    {
    using (BinaryReader reader = new BinaryReader(FileUpload1.PostedFile.InputStream))
    {
    byte[] image = reader.ReadBytes(FileUpload1.PostedFile.ContentLength);

    ImagenesDAL.GuardarImagen(FileUpload1.FileName, FileUpload1.PostedFile.ContentLength , image);

    }
    }



    espero me puedas ayudar, gracias de todas formas

    ResponderEliminar
  96. hola nelson

    dices que tienes un error y no guarda la imagen, pero cual seria ese error, siemrpe ayuda conocer el mensaje del problema

    ademas el connection string esta definido en el web.config podrias tomarlo de alli

    o sino guiarte por
    http://www.connectionstrings.com/sql-server-2008

    saludos

    ResponderEliminar
  97. Hola amigo!! tienes la descarga de imagenes una ala ves!!! que tal si quiero descargar varias a la ves, sera posible esto?

    agradeceria tu ayuda

    ResponderEliminar
  98. Hola Leandro que tal, he revisado tu post y me ha parecido muy bueno.
    Ahora quisiera saber
    como obtener la imagen guardada en la BD como Byte[], convertirla de nuevo a imagen y colocarla tal vez en un control Image de mi Pagina web.

    ResponderEliminar
  99. Unknown para mostrar una imagen en un control image se necesita..

    1-crear una pagina donde vamos a descargar la imagen de la base de datos del campo blob, y esta variable la vamos a recibir como un array de bites.... esta debe ser una nueva pagina ejemplo mostrarimagen.aspx... para hacer mas dinamica la cosa vamos a pasarle el id de la imagen a mosrrar por el metodo get
    mostrarimagen.aspx?id=25

    2-una ves teniendo la imagen debemos escribir esta en pantalla con response

    3-en el control donde queramos mostrar la imagen en la propiead imageurl le debemos asignar la direccion url de la pagina creada

    un ejemplo...

    se crea una nueva pagina mostrarimagen.aspx.......

    en el evento load recuperamos la imagen de la base de datos eso no lo explicare....

    para recibir parametros get es de la siguiente manera

    Request.QueryString("id")
    ''esto servira para poder usar esta pagina para mostrar cualquier imagen

    ''una ves echo la consulta en la base de datos recuperamos la iumagen

    Dim imagen() As Byte = 'imagen'
    Response.ContentType = "image/jpeg"
    ''esto depende de que tipo de imagen sea Response.BinaryWrite(imagen)

    eso es todo lo que se necesita....


    ahora en la pagina donde este el control image le asignamos en la priopiedad imageurl="mostrarimagen.aspx?id=20"

    y listo eso es todo

    ResponderEliminar
  100. hola Hector

    el tema es que el link apunta a un solo archivo o imagen a la vez, si quieres descargar varios habria que ver de poner algun checkbox o seleccion y algun boton que tomes esa seleccion y arme algun zip para enviarlo por el Request

    o sea la respuesta solo puede ser una sola, la uncia forma es agrupando los archivos seleccionados en un zip

    saludos

    ResponderEliminar
  101. hola Unknown

    pero me pregunto has analizado el articulo?
    porque es muy raro que realices esta pregunta si lo hiciste

    poner un byte[] en un control image de la pagina no se puede, requieres que algo lo ponga en el Response, es por eso que se hace uso de un handler para esa tarea

    el control imagen de la pagina se asocia a ese handler para que muestre la imagen, peor esto esta mencionado en el articulo

    saludos

    ResponderEliminar
  102. Leandro pero como se podria hacer esto?? e encontrado informacion pero cuando los archivos estan directamente en el servidor y no en la base de datos!!

    alguna idea??? te agradeceria tu ayuda!!

    ResponderEliminar
  103. hola Hector

    la tecnica es la misma solo cambia el lugar donde recuperas la informacion, si los archivo estan en la db en lugar de usar la clase File de .net usarias una query a la db para recuperar el array de byte que forma el archivo

    en este mismo articulo aplcia esa tecnica, quizas debas usar el File.WriteAllBytes() para crear un archivo fisico que comprimir, aunque si puede encontrar la vuelta para comprimir desde un Stream se peude pasar el byte[] a stream para enviarlo al zip sin archivo intermedio

    saludos

    ResponderEliminar
  104. Hola Leandro

    muy bueno lo que me recomendaste, use File.WriteAllBytes() para guardar las imagenes en el servidor!! no sabia que se podia!!!

    y despues comprimi la carpeta donde estaban con DotNetZipLib y luego la mande a descargar!!!

    Mucha grascias por tu ayuda!!!

    ResponderEliminar
  105. Hola Leandro por favor necesito de tu ayuda lo que pasa es que estoy empezando en lo que es la programacion y estoy creando un proyecto persona para manejar profesores de un colegio y necesito agregarle la foto al cada profesor que registre en el sistema y no le encuentro camino para hacerlo estoy utilizando Linq, VB.Net en ASP.net

    por favor agradeceria mucho de tu acostumbrada ayuda.-

    Gracias de antemano.-

    ResponderEliminar
  106. hola Jose

    no analizaste el articulo

    [ASP.NET] GridView – Edición Empleados

    alli implemento lo que creo quieres lograr

    saludos

    ResponderEliminar
  107. Hola Leandro

    Antes que nada agradecerte ya que es muy util toda la informacion que compartes.

    Podrias dar una revisada a este thread por favor, estoy un poco atorado en ello, es respecto a guardar una imagen en base de datos.
    Para ello tendria que subir la imagen al servidor?
    Es la unica causa que se me ocurre para que no funcione, ya que en el ambiente local no hubo problema alguno

    Gracias por tu tiempo

    http://social.msdn.microsoft.com/Forums/es-ES/aspnetmvces/thread/c0ef5b6c-a6c4-4038-9cc4-c94ce8f4b112

    ResponderEliminar
  108. hola AlfredMeza

    respondi en el foro

    saludos

    ResponderEliminar
  109. Muchas gracias Leandro, podrías echarle otro vistazo por favor, a lo mejor es algo muy noob que estoy obviando o no sé te agradecería mucho si puedieras ver.

    http://social.msdn.microsoft.com/Forums/es-ES/aspnetmvces/thread/c0ef5b6c-a6c4-4038-9cc4-c94ce8f4b112

    Gracias

    ResponderEliminar
  110. Hola Leandro, Excelente tutorial.

    Una pregunta:

    ¿como podría hacer para que esos datos ingresados me lo muestre al principio?.Es posible eso!!

    Espero me ayudes. Gracias

    ResponderEliminar
  111. hola Abel

    a que datos ingresados haces referencia? a la imagen

    ademas al principio de quien? cuando se carga la pagina, o cuando seleccionas una imagen

    saludos

    ResponderEliminar
  112. hola!! Me refiero a un registro nuevo, cuando se inserta uno. "te lo muestra al final" , mi pregunta es si ese dato nuevo se muestre al principio, mejor dicho como si fuera el primer dato ingresado.

    Cuando se carga la pagina de ListarEmpleado

    ResponderEliminar
  113. hola Abel

    si el registro lo agregas a una base de datos podrias ordenarlo de forma descendente

    SELECT * FROM Tabla ORDER BY campo DESC

    pero si lo agregas a un datatable (que imagino conservas en la Session) podrias utilizar el metodo Insert() para indicar el index donde quieres agregarlo


    saludos

    ResponderEliminar
  114. Gracias Leandro!! Por el aporte, Me fue de ayuda el de la base de datos Muy Agradecido...

    ResponderEliminar
  115. Cordial saludo leandro estuve probando tu código y ps en un proyecto q cree nuevo no me esta mostrando la imagen aparece una "x"
    ya he revisado y no puedo hallar con el error

    ResponderEliminar
  116. hola jonathan

    la X quiere decir que no pudo recuperar la imagen

    estas implementando un handler para recuperar la imagen? si es asi al poner un breakpoint puedes validar que ingresa, o sea resuelve el handler

    recuerda que debes configurar este en el web.config para que funcione

    saludos

    ResponderEliminar
  117. Gracias leandro si era configurar el halder en web.config

    ResponderEliminar
  118. Hola Leandro, excelente tu post! una consulta yo necesitaría mostrar una imagen en pantalla y que con un boton o algo me pase a la siguiente. Eso seria posible?

    ResponderEliminar
  119. Leandro lo que quiero decir es, si existe alguna posibilidad de agregar un control DataPager al Gridview y que me las muestre de a un por ejemplo. Se puede realizar eso?

    ResponderEliminar
  120. hola MarianoNct

    no creo que el GridView tenga esta funcionalidad, quizas se pueda simular si paginas de a un item

    pero podrias ver de utilizar un

    DetailsView (Control de servidor Web)

    con este control podrias mostrar de un item, y si lo paginas con paginas de 1, podrias pasar de un registro a otro

    saludos

    ResponderEliminar
  121. En un DetailsView puedo mostrar las imagenes desde la base de datos tal como tu lo hiciste en el ejemplo con el GridView?

    ResponderEliminar
  122. hola MarianoNct

    el control DetailsView es muy similar al GridView ya que en este se puede definir un template, solo que esta pensando para mostrar de a un item

    en este pondrias un control Image cuya url la definas mediante el Eval() para asignar el id en el querystring del handler que nos devolvera la image, digo si es que la imagen esta en la tabla de tu db

    saludos

    ResponderEliminar
  123. Excelente informacion Leandro! Muchísimas gracias por tu ayuda.
    Saludos

    ResponderEliminar
  124. Muy bueno el aporte. Es la primera vez que hago algo así.
    Quisiera saber en donde va el siguiente código, porque no logro que me lo reconozca.
    public static void GuardarImagen(string nombrearchivo, int length, byte[] imagen)
    {
    using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["default"].ToString()))
    {
    conn.Open();

    string query = @"INSERT INTO Imagenes (nombre, length, imagen)
    VALUES (@name, @length, @imagen)";

    SqlCommand cmd = new SqlCommand(query, conn);

    cmd.Parameters.AddWithValue("@name", nombrearchivo);
    cmd.Parameters.AddWithValue("@length", length);

    SqlParameter imageParam = cmd.Parameters.Add("@imagen", System.Data.SqlDbType.Image);
    imageParam.Value = imagen;

    cmd.ExecuteNonQuery();

    }

    }

    Desde ya muchas gracias.

    ResponderEliminar
  125. hola Edu

    imagino deberia ir en la accion del boton que confirma la operacion que crea la entidad en donde subirias la imagen al sitio

    ese codigo podrias usarlo como lo realizo en el articulo

    saludos

    ResponderEliminar
  126. Que tal Leandro , muchas gracis por publicar el articulo es de gran utilidad, a mi me funciono bien, pero tengo un detalle cuando muestro la imagen en mi navgador ie version 10 con win8 funciona muy bien, pero cundo lo quiero ver en otra pc con windows xp y navegador ie version 8 marca una crusita en lugar de desplegar la imagen. Cabe clarar que funciona bien en win 2008, 2003, win 7 y 8, pero en xp no, sabes que se pueda deber?.

    ResponderEliminar
  127. hola raulale79

    si en IE8 luego de cargada la pagina presionas F12 para abrir la developer tool, he inspeccionas la imagen, que url puedes visualizar ?

    es una url valida, si la llevas al IE10 resuleve la imagen, puedes verla

    es raro que en un browser funcione y en otro no, has probado en FireFox o Chrome?

    saludos

    ResponderEliminar
  128. Hola que tal Leandro, gracias por contestar, fijate que cuando inspecciono el elemento y copio la url de la imagen y la copio y pego en un nuevo explorer este despliega una ventana que me dice si quiero abrir o no el archivo, lo que me da a entender es que si tiene acceso a la carpeta y al archivo fisico. cuando le doy abrir como que se cicla ya que abre un nuevo explorer y me vuelve a hacer la pregunta de como desdeo abrir el archivo, asi n veces. No he podido instalar otro navegador ya que es una maquina que esta en produccion y no puedo hacer instalaciones de otra indole. Este caso si esta muy raro, no se si pueda ser el ie o el codigo, pero si fuera el codigo no funcionara en las demas pc's.

    ResponderEliminar
  129. hola Raul

    como es la url que copias ? es del estilo http://sitio/carpeta/imagen.jpg

    porque si es del estio c:\...
    entonces es incorrecto, eso no es una url sino el acceso a una carpeta fisica

    no es necesario que instales nada en el servidor, se supone que tienes que acceder al sitio dewde otra pc conectada la red, alli si puedes instalar otro browser si lo necesitas

    saludos

    ResponderEliminar
  130. Hola que tal Leandro ya pude resolver el problema, simplemente cambie el codigo en el Generic Handler, cabe aclarara que el codigo lo tome de otro foro. Mira este es el codigo que tenia en el ProcessRequest del Handler.ashx:

    context.Response.ContentType = "Image/gif"; context.Response.WriteFile(ImageId); context.Response.End();


    por este otro:

    string path = ImageId;
    Image img = Image.FromFile(path);
    img.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Gif);
    context.Response.ContentType = "image/gif";
    context.Response.End();


    El cambio simplemente se baso en tomar una imagen fisica que esta en un servidor compartido, convertira en arreglo de bits y ese arreglo de vits pintarlos como imagen, con eso basto para que funcionara.

    no entiendo el porque de la icompatibilidad ya que si funcionaba en los demas windows pero en windows xp no.

    Pero aqi dejo esta expereicna por si a alguien mas se tepa con esto.

    Mucha sgracias por tu ayuda Leandro.

    ResponderEliminar
  131. Hola Leandro, te postie pero creo que no salio por si se repite el msj.

    Quería preguntarte si sabes como hacer lo siguiente... Presionar un boton, y que se guarde una imagen predeterminada en la BD sin utilizar un File Update, es decir solo se ve el boton en la pantalla. El problema es que nose como guardar la imagen en una variable... la imagen esta en el C y se llama Prueba1.jpeg.. tenes idea de como puedo resolver este tema?

    Muchas Gracias por tus aportes.
    Mariano

    ResponderEliminar
  132. hola MarianoNct

    la imaen en si es un array de byte, por lo que si usas el

    File.ReadAllBytes()

    podrias recuperarla a una avariable para posteriormente asignarla al parametro que la lleva al campo de la tabla

    saludos

    ResponderEliminar
  133. buen día sr. leandro, excelente articulo, una consulta utilice la parte para descargar la imagen una vez guardada, pero en ie y firefox descarga los archivos sin la extension del mismo, probe con safari, opera y chrome y trabaja perfectamente. alguna idea de por que y como solucionar el inconveniente?

    ResponderEliminar
  134. hola Willians

    validaste que el nombre del archivo tenga extension cuando defines

    Response.AddHeader()

    quizas si alli no defines la extension al descargar llegue sin esta al browser

    saludos

    ResponderEliminar
  135. Buenas Tardes, Tiene usted razón, solo le pasaba el titulo, concatene el titulo y la extensión,

    la extensión la estaba guardando como content-type (ejemplo: application/pdf).

    y se resolvio el error en el IE, sigue en firefox me parece que es por que el titulo tiene espacios en blanco, voy a probar quitandolos.

    ResponderEliminar
  136. Hola podrias ayudarme como cargar una fotografia con fileupload a una Image para guardar en sql desde C# estoy aprendiendo a utilizar C#.net, quiero guardar en una tablña docentes que contine nombre, ci, ciudad, email y fotografia.

    ResponderEliminar
  137. hola Naty

    pero este articulo justamente explica como lograr lo que estas planteando

    pudiste analiza el codigo del articulo? hay algun punto que no se entienda?

    saludos

    ResponderEliminar
  138. de hecho si lo he leido pero me indica como cargar la imagen en un datagrid pero yo necesito cargar la imagen en un image estoy trabajando en visual estudio.net

    ResponderEliminar
  139. hola Naty

    no importa donde la necesites cargar la tecnica es la misma

    defines un handler que es quien pondra la imagen en el Response recuperando los byte[] del campo de la db que contiene el archivo

    esa url es la que asignar el ImageUrl del control

    esto si es que la imagen como archivo, o sea byte[] esta en la tabla, si solo tienes el nombre del archivo de la imagen eso es diferente

    saludos

    ResponderEliminar
  140. Leandro, si a todo esto que explicas en tu articulo, me gustaría añadirle una funcionalidad, tener una carpeta en mi computadora (P. ejemplo: C:\Archivos) y quisiera que al momento de yo poner un documento digamos de office, o una imagen o un pdf dentro de esa carpeta, el grid en donde se muestran los archivos se actualice, como sincronizando mi carpeta en el escritorio con el grid y desde luego poder desde el grid descargar y visualizar el archivo, que me aconsejas?



    ResponderEliminar
  141. hola Iván

    usando solo asp.net lo que planteas no se puede lograr

    ahora si puede desarrollar alguna aplicacion residente como ser un Windows Service y usar el

    FileSystemWatcher

    podrias monitorear la carpeta y ante la presencia del archivo que se lance la accion que subiria este quizas por FTP, HTTP o algun otro protocolo al servidor

    pero necesitas de algo ejecutando local en la pc para poder detectar y subir el archivo

    saludos

    ResponderEliminar
  142. Estimado Leandro tengo un inconveniente las extenciones (GIF o JPG ...) del archivo no están guardadas en la base datos , creo que por eso solo me muestra algunas imágenes, como podría solucionar esto.

    ResponderEliminar
  143. LEandro verifique y carga las imagenes correctamente en Iexplorer más no en chrome por que puede ser?

    ResponderEliminar
  144. hola chrcito

    recuerdo que una vez me paso algo similar y se debio al formato de la imagen

    prueba recuperar el archivo de la imagen, abrelo con el ms paint y grabalo como una imagen nueva, prueba validar si esa imagen como archivo puedes verla en Chrome

    a veces sucede que el formato con que fue generada la imagen no se visualiza, solo es cuestion de editar y volver a grabar la imagen

    saludos

    ResponderEliminar
  145. Ing. gracias por sus excelentes aportes. Mi pregunta es con un contro HTML Editor de Ajax Control Kit, quiero guardar el contenido de una tesis en una base de datos. Es posible hacerlo ? o cual seria la mejor forma de realizar esta tarea

    ResponderEliminar
  146. hola..no puedo ver el codigo de los botones, descargue el proyecto eb vb. el proyecto hecho en c# si puedo ver el codigo que tienen los botones pero en el de vb no.

    ResponderEliminar
  147. hola lukaz

    pero que control usas? seria algo como este

    http://htmleditor.codeplex.com/

    si es un control ajax deberias poder accederlo desde el codigo de la pagina en el servidor y tomar su contenido para insertarlo en la db
    pero no sabria decirte que evento o propiedad usar porque no se que control usas o en que accion vas a realizar el registro

    saludos

    ResponderEliminar
  148. hola Carmen

    descargue el codigo del articulo en vb.net y fui al archivo SubirImagen.aspx.vb alli pude ver el codigo de los botones sin problema

    no vayas al diseñador de la pagina ve directo al codigo asociado para ver los eventos de los botones

    saludos

    ResponderEliminar
  149. SubirImagen.aspx.vb
    este archivo no lo muestra nose pero no aparece, solo las clases he podido ver pero nada mas de codigo.

    ResponderEliminar
  150. hola Carmen

    no puedes visualizarlo en el solution explorer, pero si accedes con el explorador de windows a la carpeta donde esta el proyecto puedes verlo?

    si accedes al codigo de aspx, que muestra el VS?

    estas programando en c# o vb.net ?

    saludos

    ResponderEliminar
  151. Las imágenes no se muestran cuando lo subo al servidor, es decir cuando hago la prueba localmente carga perfectamente pero al subir la aplicación web al servidor no se muestran las imágenes. esta es la página para que puedas ver:
    www.creativa.com.pe

    también abrí un nuevo tema en el foro pero parece que quedo en olvido por favor ayúdame.

    http://social.msdn.microsoft.com/Forums/es-ES/1260a75c-83e9-4cac-8d1a-1ebe41827441/no-se-muestran-imgenes-de-gridview-usando-un-handler?forum=netfxwebes#502bc293-1465-46be-b05b-c9baa960136b

    ResponderEliminar
  152. Leandro te respondí también en el foro no me dejes de lado por favor.

    ResponderEliminar
  153. Leandro me apoyas en el foro porfas ya t envie la imagen.

    http://social.msdn.microsoft.com/Forums/es-ES/1260a75c-83e9-4cac-8d1a-1ebe41827441/no-se-muestran-imgenes-de-gridview-usando-un-handler?forum=netfxwebes#502bc293-1465-46be-b05b-c9baa960136b

    ResponderEliminar
  154. Leandro por fas ayúdame en el foro hasta ahora no le encuentro solución.

    http://social.msdn.microsoft.com/Forums/es-ES/1260a75c-83e9-4cac-8d1a-1ebe41827441/no-se-muestran-imgenes-de-gridview-usando-un-handler?forum=netfxwebes#4df361fa-858e-45fa-815b-1d8ad82fbd41

    ResponderEliminar
  155. hola chrcito

    respondi en el foro

    saludos

    ResponderEliminar
  156. Estimado Leandro: He leido su articulo y me ha resultado de ayuda para algunos conocimientos, pero quisiera saber como se guarda un archivo (de cualquier tipo) en una base de access en el tipo de datos "Datos Adjuntos", mediante una instruccion SQL con vb2010.
    Desde ya muy amable de su parte.

    Jorge

    ResponderEliminar
  157. Leandro nuevamente yo solicitando tu ayuda en el foro
    http://social.msdn.microsoft.com/Forums/es-ES/1260a75c-83e9-4cac-8d1a-1ebe41827441/no-se-muestran-imgenes-de-gridview-usando-un-handler?forum=netfxwebes#4df361fa-858e-45fa-815b-1d8ad82fbd41

    ResponderEliminar
  158. hola chrcito

    respondi en el foro

    saludos

    ResponderEliminar
  159. Hola Leandro me parece muy bueno tu articulo, soy nueva en .net yo solo necesito descargar un archivo, pero sin cargarlo así, no se si me explico, lo que quiero es que el contenido de la carpeta files se vea en esa tabla pero sin que yo lo cargue así, no quiero usar base de datos sino descargarlos desde una carpeta que tendré en mi servidor solo que no tengo muy claro como hacerlo.

    ResponderEliminar
  160. Hola Leandro.

    Realmente tengo problemas con un gridview porque necesito mostrar diferentes archivos por ejemplo pdf, word, excel y winrar los cuales vienen de base de datos, para que el usuario pueda diferenciarlo los tipos de archivos para lo cual necesito mostrar cada archivo con con su logo respetivo, los logos no lo tengo en base de datos sino afuera. Gracias, espero que me pueda ayudar.
    Un saludo cordial

    ResponderEliminar
  161. Hola Leandro: Tendras algún articulo para bajar/leer un archivo guardado como imagen de bits en una tabla de access mediante vb 2010 o superior.
    Gracias de antemano.

    ResponderEliminar
  162. hola JorgeD

    la tecnica con Access es la misma que explico en este articulo
    solo que ne lugar de usar SqlConnection usarias OleDbConnection, en lugar de SqlCommand usarias OleDbCommand
    peor el resto es igual, recuperas del campo un byte[] que seria la imagen

    saludos

    ResponderEliminar
  163. Hola Leandro,

    una duda: como puedo hacer para comprimir la imagen captada por el Fileupload antes de convertirla a un array de bytes? suponiendo que estoy trabajando en webform y no puedo (debo) usar rutas locales

    ResponderEliminar
  164. hola AmriEdardna

    podrias usar las librerias de .net para comprimir

    How to: Compress and Extract Files

    Create Zip File from byte[]

    seguramente en tu caso el compressedFileStream no lo envies en el response, sino que lo quieras grabar en un archivo o en la db

    lo importante es ver como usa el MemoryStream de originalFileStream pasandole el byte[] que luego agrega al zip

    saludos

    ResponderEliminar
  165. Hola leandro excelente tu blog pero tengo un problema he hecho funsionar tu ejemplo pero cuando creo otra BD y copio la tabla imagen ya no funsiona el ejemplo ,verifique y la unica diferencia entre las dos tablas era el collation, podria indicarme si te ocurrio este problema.

    ResponderEliminar
  166. hola Unknown

    pero no funciona porque obtienes algun error, o porque quizas no inserta el registro ?

    si es un error cual es el mensajes que obtienes

    la db sigue siendo sql server? usas el tipo de dato image o varbinary para definir el campo

    saludos

    ResponderEliminar
  167. Hola esta muy bien explicado, pero estoy buscando algo muy similar pero igual en aplicación web necesito subir archivos, asignarles un nombre, en cas de tener que onerlos dentro de una carperta generar la carpeta(darle nombre y guardar dentro el archivo), pero en lugar de descargarlos los debe abrir cabe mencionar que todos seran PDF, y cuando los abre si deseo realizar un comentario en PDF que ese comentario se guarde en una base de datos de sql y sobre ese mismo pdf sin importar el n° de comentarios(osea que no genere un nuve documento ala hora de guardar cada comentario). espero me puedan ayudar por que no encontre mucha información en especifico de como hacer la parte para subir los archivos, generar carpetas y asignarles nombre, esto es como MIS DOCUMENTO DE WINDOWS eso es lo que necesito en aplicacion asp.net c#

    ResponderEliminar
  168. hola Johana

    para generar carpetas usas el Directory.CreateDirectory()

    para grabar con diferente nomre simplemente lo defines cuando realizas el FileUpload.SaveAs() es alli cuando generas el nuevo nombre que necesites

    lo que no entendi es el tema de los comentarios, habia entendido que defines los archivos en una carpeta por eso el uso de la db no veo donde aplica

    saludos

    ResponderEliminar
  169. Hola, tengo el mismo problema solo que ya implemente casi todo los comentarios y sigue mostrando mi fileupload que es false

    solo que si lo saco del update panel y del ContentTemplate a la hora de realizar la pregunta en el boton m dice q es true
    if (FileUpload1.HasFile)

    <%@ Page Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="PruebaFile.aspx.cs" Inherits="SITI.ControlAsistencia.Web.UI.Forms.PruebaFile" %>





    <%--

    --%>





    <%--
    --%>



    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;

    namespace SITI.ControlAsistencia.Web.UI.Forms
    {
    public partial class PruebaFile : System.Web.UI.Page
    {
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    protected void Upload_File(object sender, EventArgs e)
    {
    if (FileUpload1.HasFile)
    { }
    }

    }
    }
    tengo un archivo cargado

    pero si descomento me sale siempre falso... ojala puedan ayudarme


    saludos

    ResponderEliminar
  170. hola naomy

    el control FileUpload no funciona dentro de un updatepanel deberias usar el control de ajax toolkit

    asyncfileupload

    saludos

    ResponderEliminar
  171. Excelente la información y la explicación Leandro. una pregunta hay forma de que se pueda descargar todas las imágenes al hacer click a un botón por ejemplo.

    ResponderEliminar
  172. hola luis

    podrias crear un zip en el servidor incluyendo todas las imagenes, luego enviar el zip en el Response para que lo descargue

    saludos

    ResponderEliminar
  173. buen dia , quiero guardar imagenes en una base de datos
    lo malo es que me preocupa el hecho de que mi bd va a crecer mucho y que generar respaldo va a demorar
    alguna idea de cual es la manera optima de manejar imagenes en la base de datos o que gestor base de datos es mejor utilizar para estos casos?? muchas gracias.

    ResponderEliminar
  174. Que tal Leandro... Excelente Blog

    Yo quería solicitar tu ayuda, estoy desarrollando un proyecto FTP Client en VB.NET(2008), necesito saber si existe un archivo
    en el servidor, si el archivo existe que me despliegue un msgbox, que diga "SI EXISTE", lo que quiero lograr con ese código
    es que al momento de subir un archivo al servidor, si ese archivo ya existe, que me genere una copia del mismo en el servidor para que no sobre escriba el archivo ya existente.

    Agradezco el apoyo...Saludos.

    ResponderEliminar
    Respuestas
    1. hola
      Con el link del ftp del archivo puedes validar si este existe
      How to check if file exists on FTP before FtpWebRequest
      basicamente lo que haces es intentar recuperarlo, si puede hacerlo es que existe
      saludos

      Eliminar