13 votes

Rendu dynamique d'une asp:Image à partir d'une entrée BLOB en ASP.NET

Mon objectif est le suivant. Je veux donner à l'utilisateur la possibilité de télécharger un fichier image, de stocker l'image dans un BLOB dans le serveur SQL, puis d'utiliser cette image comme logo dans d'autres pages du site.

Pour ce faire, j'ai utilisé

   Response.Clear();
   Response.ContentType = "image/pjpeg";
   Response.BinaryWrite(imageConents);
   Response.End();

mais pour ce faire, j'utilise un contrôle utilisateur à l'endroit où je veux afficher l'image. Je voudrais le faire si possible en utilisant un contrôle asp:Image, ou même un vieux contrôle d'image html. Est-ce possible ?

18voto

Fredrik Kalseth Points 6633

Ajoutez un "Generic Handler" à votre projet web, nommez-le quelque chose comme Image.ashx. Mettez-le en œuvre comme suit :

public class ImageHandler : IHttpHandler
{

    public void ProcessRequest(HttpContext context)
    {
        using(Image image = GetImage(context.Request.QueryString["ID"]))
        {    
            context.Response.ContentType = "image/jpeg";
            image.Save(context.Response.OutputStream, ImageFormat.Jpeg);
        }
    }

    public bool IsReusable
    {
        get
        {
            return true;
        }
    }
}

Il suffit maintenant d'implémenter la méthode GetImage pour charger l'image avec l'ID donné, et vous pouvez utiliser la méthode

<asp:Image runat="server" ImageUrl="~/Image.ashx?ID=myImageId" /> 

pour l'afficher. Vous pouvez également envisager de mettre en place une forme de mise en cache dans le gestionnaire. Et n'oubliez pas que si vous voulez changer le format de l'image en PNG, vous devez utiliser un MemoryStream intermédiaire (car les PNG nécessitent un flux pouvant être recherché pour être sauvegardés).

9voto

FlySwat Points 61945

Vous pouvez encoder le contenu de l'image en BASE64 directement dans l'attribut SRC, mais je crois que seul Firefox l'interprétera comme une image.

En général, je crée un HTTPHandler très léger pour servir les images :

using System;
using System.Web;

namespace Example
{  
    public class GetImage : IHttpHandler
    {

        public void ProcessRequest(HttpContext context)
        {
            if (context.Request.QueryString("id") != null)
            {
                Blob = GetBlobFromDataBase(id);
                context.Response.Clear();
                context.Response.ContentType = "image/pjpeg";
                context.Response.BinaryWrite(Blob);
                context.Response.End();
            }
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}

Vous pouvez y faire référence directement dans votre balise img :

<img src="GetImage.ashx?id=111"/>

Vous pouvez également créer un contrôle de serveur qui le fait pour vous :

using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Example.WebControl
{

    [ToolboxData("<{0}:DatabaseImage runat=server></{0}:DatabaseImage>")]
    public class DatabaseImage : Control
    {

        public int DatabaseId
        {
            get
            {
                if (ViewState["DatabaseId" + this.ID] == null)
                    return 0;
                else
                    return ViewState["DataBaseId"];
            }
            set
            {
                ViewState["DatabaseId" + this.ID] = value;
            }
        }

        protected override void RenderContents(HtmlTextWriter output)
        {
            output.Write("<img src='getImage.ashx?id=" + this.DatabaseId + "'/>");
            base.RenderContents(output);
        }
    }
}

Il pourrait être utilisé de la manière suivante

<cc:DatabaseImage id="db1" DatabaseId="123" runat="server/>

Et bien sûr, vous pouvez définir le databaseId dans le codebehind si nécessaire.

5voto

Taliesin Points 221

Il n'est pas souhaitable de servir des blobs à partir d'une base de données sans mettre en place une mise en cache côté client.

Vous devrez gérer les en-têtes suivants pour prendre en charge la mise en cache côté client :

  • ETag
  • Expiration
  • Dernière modification
  • Si-appariement
  • Si-Non-concordance
  • Si modifié depuis
  • Si-non-modifié-depuis
  • Sauf modification depuis

Pour un gestionnaire http qui fait cela, voir : http://code.google.com/p/talifun-web/wiki/StaticFileHandler

Il dispose d'une aide sympathique pour servir le contenu. Il devrait être facile de lui passer un flux de base de données. Il fait également de la mise en cache côté serveur, ce qui devrait permettre d'alléger la pression sur la base de données.

Si vous décidez de diffuser du contenu en continu à partir de la base de données, des fichiers PDF ou des fichiers volumineux, le gestionnaire prend également en charge 206 requêtes partielles.

Il prend également en charge les compressions gzip et deflate.

Ces types de fichiers bénéficieront d'une compression supplémentaire :

  • css, js, htm, html, swf, xml, xslt, txt
  • doc, xls, ppt

Certains types de fichiers ne bénéficieront pas d'une compression supplémentaire :

  • pdf (pose des problèmes avec certaines versions d'IE et est généralement bien compressé)
  • png, jpg, jpeg, gif, ico
  • wav, mp3, m4a, aac (le wav est souvent compressé)
  • 3gp, 3g2, asf, avi, dv, flv, mov, mp4, mpg, mpeg, wmv
  • zip, rar, 7z, arj

2voto

Forozco Points 31

En utilisant ASP.Net avec MVC, c'est assez facile. Vous codez un contrôleur avec une méthode comme celle-ci :

public FileContentResult Image(int id)
{
    //Get data from database. The Image BLOB is return like byte[]
    SomeLogic ItemsDB= new SomeLogic("[ImageId]=" + id.ToString());
    FileContentResult MyImage = null;
    if (ItemsDB.Count > 0)
    {
        MyImage= new FileContentResult(ItemsDB.Image, "image/jpg");
    }

    return MyImage;
}

Dans votre vue Web ASP.NET ou, dans cet exemple, dans votre formulaire Web ASP.NET, vous pouvez remplir un contrôle d'image avec l'URL de votre méthode comme ceci :

            this.imgExample.ImageUrl = "~/Items/Image/" + MyItem.Id.ToString();
            this.imgExample.Height = new Unit(120);
            this.imgExample.Width = new Unit(120);

Voilá. Il n'y a pas eu de problème avec HttpModules.

0voto

Brad Wilson Points 22910

Nous venons d'ailleurs de publier des cours qui traitent précisément de ce type de questions :

http://www.codeplex.com/aspnet/Release/ProjectReleases.aspx?ReleaseId=16449

Plus précisément, consultez l'exemple DatabaseImage.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X