Ukážeme si, jak v ASP.NET napsat vlastní generátor obrázků. Pro demonstraci bude myslím stačit vykreslovač elips. Na webu bude dostupný jako generický handler.
První přidáme do webového projektu nový soubor – Generic Handler. Pojmenujeme si ho třeba “Triangle.ashx” (ashx je přípona handlerů, kterou musíme zachovat, jinak se soubor nezpracuje):
Po vytvoření souboru se nám ukáže implementace metody ProcessRequest a vlastnosti IsReusable z rozhraní IHttpHandler.
Vlastnost IsReusable vrací, zda může být jedna instance psané třídy handleru použita pro více požadavků. Implicitně je False a bude tedy vytvořena vždy nová instance. Pro náš příklad to bude stačit.
<%@ WebHandler Language="VB" Class="Triangle" %>
Imports System
Imports System.Web
Public Class Triangle : Implements IHttpHandler
Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
End Sub
Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
End Class
Nás teď bude zajímat metoda ProcessRequest. Ta se zavolá vždy, když se na soubor handleru dotážeme prohlížečem. Musí tedy obstarat vygenerování a vrácení výsledku. Pomůže nám k tomu předaný paremetr context obsahující všechno podstatné k právě probíhajícímu požadavku. Zejména context.Request (objekt požadavku) a context.Response (objekt výsledku požadavku – to co se vrátí klientovi). Ukážeme si jak v paměti vytvořit obrázek a vrátit ho uživateli.
První nastavíme MIME typ, pomůže prohlížeči u klienta identifikovat typ souboru. Jejich přehled naleznete třeba tady. V našem případě použijeme “image/x-png” pro png obrázek.
Zbytek je už jen práce s GDI+, funkčnost je patrná z komentářů:
<%@ WebHandler Language="VB" Class="Triangle" %>
Imports System
Imports System.Web
Public Class Triangle : Implements IHttpHandler
Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
' nastaváme MIME type
context.Response.Clear()
context.Response.ContentType = "image/x-png"
' přečteme šířku a výšku, pokud nejsou zadané, zvolíme 200x50
Dim sirka As Integer, vyska As Integer
If Int32.TryParse(context.Request.QueryString("sirka"), sirka) = False Then sirka = 200
If Int32.TryParse(context.Request.QueryString("vyska"), vyska) = False Then vyska = 50
Dim font As New Drawing.Font("Arial", 15, Drawing.FontStyle.Regular, Drawing.GraphicsUnit.Pixel)
' vytvoříme bitmapu
Using image As New Drawing.Bitmap(sirka, vyska)
' vytvoříme objekt na práci s obrázkem
Using g = Drawing.Graphics.FromImage(image)
' vyplníme pozadí
g.FillRegion(Drawing.Brushes.LightCoral, New Drawing.Region(New Drawing.RectangleF(0, 0, sirka, vyska)))
' vykreslíme elipsu
g.DrawEllipse(Drawing.Pens.Blue, New Drawing.RectangleF(0, 0, sirka - 1, vyska - 1))
' vykreslit text
g.DrawString(String.Format("{0}x{1} pixelů", sirka, vyska), font, Drawing.Brushes.Black, 0, 0)
' vytvoříme buffer
Using buffer As New IO.MemoryStream()
' uložíme jako Png do bufferu
image.Save(buffer, Drawing.Imaging.ImageFormat.Png)
' buffer vypíšeme uživateli
Dim length = buffer.Length
context.Response.OutputStream.Write(buffer.ToArray(), 0, length)
End Using
End Using
End Using
End Sub
Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
End Class
Výsledek v prohlížeči je dle očekávání. Navíc podle GET parametrů “sirka” a “vyska” můžeme měnit rozměry generovaného obrázku. Například jako v tomto html kódu:
<img src="Triangle.ashx" />
<img src="Triangle.ashx?sirka=300&vyska=300" />
<img src="Triangle.ashx?sirka=400&vyska=30" />
Jeho výsledkem je zobrazení tří obrázků s různými rozměry:
Poznámka pro rejpaly: Nejdříve jsem chtěl vykreslovat trojúhelníčky, proto se handler jmenuje Triangle, ale pak jsem si to rozmyslel a screenshoty a kód už nechci předělávat :-).