IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

ASP.NET Discussion :

Image stockée en base dans un GridView


Sujet :

ASP.NET

  1. #1
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut Image stockée en base dans un GridView
    Salut,

    J'ai une appli WinForms qui gère une base de données de DVD. L'image de la jaquette de chaque DVD est stockée directement en base sous forme de BLOB. Jusque là pas de problème...
    Maintenant, j'ai aussi une page ASP.NET très simple qui permet de parcourir la liste des films dans cette base. Je ne connais pratiquement pas ASP.NET, j'ai fait l'essentiel de la page avec le designer en ne tapant quasiment aucun code à part la requête SQL. J'aimerais ajouter une colonne qui affiche l'image, mais la classe ImageField permet seulement de spécifier une URL, et non l'image elle-même...
    L'objet renvoyé par le provider ADO.NET est de type byte[]. Dans mon appli WinForms, je recrée l'image de cette façon:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    byte[] imgBytes = (byte[])(dataReader["cover"]);
    Cover = Image.FromStream(new MemoryStream(imgBytes));
    Seulement en ASP.NET je ne gère pas moi-même les données renvoyées par la base, c'est fait automatiquement par le GridView, et donc je ne peux pas faire la même chose...
    En dernier recours, je stockerai les images sous formes de fichiers externes à la base, mais je préfèrerais éviter ça, c'est plus pratique d'avoir un seul fichier.

    J'ai une petite piste: en créant une classe dérivée de DataControlField, je pourrais peut-être enregistrer les données binaires de l'image dans un fichier, et donner l'URL de ce fichier... mais c'est pas une solution très élégante, surtout que ça va regénérer l'image à chaque fois.

    Si vous avez une meilleure idée, je suis preneur... merci d'avance !

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Bon, j'ai essayé de mettre en oeuvre mon idée... j'ai créé une classe StoredImageField qui hérite de ImageField, de façon à générer le fichier image avant de renvoyer une URL vers ce fichier... c'est pas très intuitif d'ailleurs
    Seulement, j'ai un petit problème... comment référencer cette classe dans le code ASPX ?
    Actuellement les colonnes du DataGrid sont définies comme ça (par le designer):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
                        <Columns>
                            <asp:BoundField DataField="id" HeaderText="Id" InsertVisible="False" ReadOnly="True"
                                SortExpression="id"></asp:BoundField>
                            <asp:BoundField DataField="title" HeaderText="Titre" SortExpression="title" />
                            <asp:BoundField DataField="director_name" HeaderText="Réalisateur" SortExpression="director_name" />
                            <asp:BoundField DataField="year" HeaderText="Année" SortExpression="year" />
                            <asp:BoundField DataField="original_title" HeaderText="Titre original" SortExpression="original_title" />
                            <asp:BoundField DataField="language_name" HeaderText="Langue" SortExpression="language_name" />
                        </Columns>
    j'ai essayé d'ajouter ça comme champ:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
                            <StoredImageField DataImageUrlField="cover" HeaderText="Image" />
    mais evidemment ca ne fonctionne pas... comment faire pour référencer ma classe ? Pour un user control, on peut faire une directive Register, mais là c'est pas un controle... bref je suis bloqué pour l'instant.

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Bon, ben j'ai réussi
    Comme quoi je pouvais m'en sortir tout seul... avec un peu de chance ca servira a quelqu'un.

    J'ai appliqué la technique décrite plus haut (enregistrer l'image dans un fichier et envoyer l'url du fichier), et j'ai ajouté la colonne par le code vu que j'ai pas trouvé comment le faire dans le .aspx.

    J'ai trouvé une astuce pour ne pas regénérer le fichier à chaque fois: je calcule le hash MD5 de l'image en base, et si le fichier <MD5>.jpg n'existe pas, je le génère à partir des données de la base. De cette façon, si l'image en base est modifiée, le fichier sera regénéré.

    Le code de la classe StoredImageField:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
     
        public class StoredImageField : ImageField
        {
            protected override string FormatImageUrlValue(object dataValue)
            {
                if (dataValue == null || dataValue is DBNull)
                    return "img/no_image.jpg";
     
                try
                {
                    string url;
                    byte[] bytes = (byte[])dataValue;
                    MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
                    byte[] hash = md5.ComputeHash(bytes, 0, bytes.Length);
                    url = "img/" + ByteArrayToHex(hash) + ".jpg";
                    string filename = HostingEnvironment.MapPath(Path.Combine(HostingEnvironment.ApplicationVirtualPath, url));
                    if (!File.Exists(filename))
                    {
                        BinaryWriter wr = new BinaryWriter(new FileStream(filename, FileMode.CreateNew, FileAccess.Write));
                        wr.Write(bytes);
                        wr.Close();
                    }
                    return url;
                }
                catch (Exception)
                {
                    return "img/bad_image.jpg";
                }
            }
     
            public string ByteArrayToHex(byte[] bytes)
            {
                StringBuilder sb = new StringBuilder();
                foreach (byte b in bytes)
                {
                    sb.AppendFormat("{0:X2}", b);
                }
                return sb.ToString();
            }
     
        }
    La méthode FormatImageUrlValue renvoie une URL en fonction des données du champ associé à la colonne. En l'occurrence, les données sont le contenu binaire de l'image... donc je génère un fichier et je renvoie son URL.

    J'ai instancié le StoredImageField comme ça dans le Page_Load:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
            if (!IsPostBack)
            {
                StoredImageField imgfld = new StoredImageField();
                imgfld.HeaderText = "Image";
                imgfld.DataImageUrlField = "cover";
                grdMovies.Columns.Insert(1, imgfld);
            }
    Avec le recul, je dois admettre que l'architecture de ma base de données est pas idéale... j'aurais peut-être dû enregistrer les images hors de la base. D'un autre côté, l'utilisation "web" n'était pas l'objectif principal, et je n'avais pas conçu mon appli dans ce but, c'est juste un "gadget" que j'ai ajouté après. Et pour une appli Windows, c'est plus pratique d'avoir sa "DVDtheque" dans un seul fichier que dans plusieurs...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 6
    Dernier message: 05/06/2014, 08h23
  2. Réponses: 2
    Dernier message: 24/01/2008, 19h58
  3. [MySQL] Images stockées en base selon tutoriel de BiD0uille
    Par jomannix dans le forum PHP & Base de données
    Réponses: 20
    Dernier message: 29/05/2007, 14h26
  4. [MySQL] Afficher une image stocké en base données
    Par Blo0d4x3 dans le forum PHP & Base de données
    Réponses: 6
    Dernier message: 19/06/2006, 17h02
  5. [Forms] Afficher une image stockée en base
    Par oramine dans le forum Forms
    Réponses: 12
    Dernier message: 01/02/2005, 14h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo