3 votes

Renvoi d'une image redimensionnée à partir de la base de données via .ashx

J'ai trouvé des questions similaires sur SO et ailleurs, mais rien qui ne corresponde exactement à ce que je recherche (ou peut-être suis-je trop bête pour relier les points entre eux !)

Je cherche à retourner une image miniature à partir d'une image pleine taille stockée en tant que varbinary(max) dans la base de données. Je vais utiliser les vignettes dans une vue de type galerie, donc la petite taille et le chargement efficace sont cruciaux. J'ai utilisé un .ashx pour retourner l'image en taille réelle dans un contrôle asp.net Image, avec le code suivant :

Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest

    Dim conn As New SqlConnection()
    conn.ConnectionString = *connectionstring*

    Dim cmd As New SqlCommand()
    cmd.Connection = conn
    cmd.CommandType = CommandType.StoredProcedure
    cmd.CommandText = "GetEmplHeadShot"

    Dim emplID As New SqlParameter("@emplID", context.Request.QueryString("emplid"))
    cmd.Parameters.Add(emplID)

    conn.Open()

    Dim myReader As SqlDataReader = cmd.ExecuteReader
    If myReader.Read Then

        context.Response.BinaryWrite(myReader("HeadShot"))
        context.Response.ContentType = "image/jpeg"

    End If
    myReader.Close()
    conn.Close()

End Sub

Je me rends compte qu'il est probablement préférable de traiter le redimensionnement lors du téléchargement, et de stocker l'image plus petite dans une colonne distincte. Mais en attendant, est-il possible de programmer le gestionnaire pour qu'il redimensionne l'image à la volée ? L'idéal serait de pouvoir passer un paramètre de chaîne de requête supplémentaire, quelque chose comme isResized à partir de la liaison de l'image, ce qui permettrait d'utiliser le même gestionnaire pour les images de taille normale et les images redimensionnées.

Tout conseil ou assistance serait grandement apprécié. Des idées sur des approches alternatives (c'est-à-dire "vous vous y prenez mal") seraient également les bienvenues.

3voto

Nathan Ratcliff Points 887

Désolé, je ne connais pas VB, mais voici un exemple si vous savez lire le C#. Vous aurez besoin d'ajouter une gestion des paramètres manquants et autres, mais ceci peut être un aperçu de votre approche de base.

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

            //Get image from database here, put into a stream
            var stream = new MemoryStream(); //this would represent the stream from your database image

            using( var original = Image.FromStream( stream ) )
            {
                using( var resized = new Bitmap(width, height, PixelFormat.Format24bppRgb) )
                {
                    using( var g = Graphics.FromImage( resized ) )
                    {
                        g.SmoothingMode = SmoothingMode.AntiAlias;
                        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                        g.PixelOffsetMode = PixelOffsetMode.HighQuality;

                        g.DrawImage( original, new Rectangle( new Point( 0, 0 ), new Size(width, height) ) );

                        var resizedStream = new MemoryStream();
                        resized.Save(resizedStream, ImageFormat.Jpeg);

                        context.Response.ContentType = "image/jpeg";
                        context.Response.BinaryWrite(resizedStream.GetBuffer());
                        context.Response.End();
                    }
                }               
            }

        }

1voto

Neil N Points 14566

Oui, au lieu de renvoyer la variable binaire directement dans la réponse, placez-la dans un objet Bitmap (via un flux de mémoire créé à partir de la variable binaire).

Redimensionner le BMP, puis l'enregistrer dans le flux de mémoire via la méthode d'enregistrement, puis restituer le flux de mémoire sous la forme d'un tableau d'octets dans la réponse.

Gardez à l'esprit que l'instanciation d'un Bitmap sur le serveur peut être très gourmande en mémoire. Si vous avez plusieurs requêtes simultanées, vous risquez de rencontrer des exceptions de type "out of memory". C'est probablement une bonne idée d'enregistrer les vignettes dans la base de données ou sur le disque lorsqu'elles sont créées, afin de ne pas avoir à les recréer à chaque requête.

1voto

Jakob Gade Points 6006

Oui, il est certainement possible d'effectuer le redimensionnement à la volée. Je vous suggère de laisser le HttpHandler créer la vignette à la première demande, en la stockant dans la base de données ou en tant qu'image sur le serveur.

Pour votre scénario, j'envisagerais probablement une solution où le gestionnaire prend les paramètres de hauteur et de largeur, redimensionne l'image et la stocke pour la réutiliser.

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