首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

ASP.NET 自訂伺服器控制項開發:即時產生縮略圖控制項完整實作

     編輯:關於C#

設計理念:無實體檔、零依賴、自包含

傳統縮略圖方案需預先產生實體檔或仰賴獨立 HTTP Handler。本控制項採用「單一類別、編譯為 DLL、無外部依賴」架構:利用 ASP.NET 網頁生命週期,將縮略圖請求導向包含控制項的頁面本身,透過查詢字串區分一般頁面請求與圖片請求,即時以 GDI+ 縮放原圖並直接輸出至回應流,完全不落地儲存。

運作流程

  1. 瀏覽器請求含控制項的頁面(如 Default.aspx)。
  2. 控制項 Render 階段輸出 <img src="Default.aspx?thumbnail=original.jpg&w=100&h=75..." />。
  3. 瀏覽器解析 img,發起第二次請求同一頁面但帶縮略圖參數。
  4. 頁面再次執行,控制項偵測到 Request["thumbnail"],啟動圖片處理邏輯:讀取原圖 → GDI+ 縮放 → 輸出至 Response.OutputStream → Response.End()。
  5. 瀏覽器接收圖片流,頁面呈現完成。

核心程式碼結構

[DefaultProperty("ImageUrl")]
[ToolboxData("<{0}:Thumbnail runat=server>")]
[Designer(typeof(Designer.ThumbnailDesigner))]
public class Thumbnail : WebControl {
    public Thumbnail() : base(HtmlTextWriterTag.Img) {
        Width = Unit.Parse("100");
        Height = Unit.Parse("75");
    }

    // 屬性:ImageUrl, JpegQuality, Width, Height, ImageAlign, AlternateText 等
    // 皆支援 ViewState 持久化、設計時編輯器、預設值

    protected override void AddAttributesToRender(HtmlTextWriter writer) {
        if (string.IsNullOrEmpty(Page.Request["thumbnail"])) {
            // 一般頁面請求:輸出指向自身的 img src(含查詢參數)
            writer.AddAttribute(HtmlTextWriterAttribute.Src,
                Page.Request.Url.AbsolutePath + "?" + GetQueryString());
            // 其他屬性:alt, align, border...
        }
    }

    private string GetQueryString() {
        var sb = new StringBuilder();
        sb.Append("thumbnail=" + Page.Server.HtmlEncode(ImageUrl));
        sb.Append("&w=" + Width.Value);
        sb.Append("&h=" + Height.Value);
        sb.Append("&bc=" + BackColor.ToArgb());
        sb.Append("&jq=" + JpegQuality);
        return sb.ToString();
    }

    protected override void OnInit(EventArgs e) {
        base.OnInit(e);
        Init += Thumbnail_Init;
        PreRender += Thumbnail_PreRender;
    }

    void Thumbnail_Init(object sender, EventArgs e) => RenderThumbnailImage(Request, Response);
    void Thumbnail_PreRender(object sender, EventArgs e) => RenderThumbnailImage(Request, Response);

    static void RenderThumbnailImage(HttpRequest request, HttpResponse response) {
        if (string.IsNullOrEmpty(request["thumbnail"])) return;

        var thumb = new Thumbnail {
            ImageUrl = request["thumbnail"],
            Width = Unit.Parse(request["w"] ?? "100"),
            Height = Unit.Parse(request["h"] ?? "75"),
            BackColor = Color.FromArgb(int.Parse(request["bc"] ?? "0")),
            JpegQuality = int.Parse(request["jq"] ?? "80")
        };

        Bitmap bmp;
        try { bmp = thumb.GetThumbnail(); }
        catch { bmp = Properties.Resources.GenerateImageError; }

        response.Clear();
        string ext = thumb.ImageUrl.Split('.').Last().ToLower();
        if (ext == "gif") {
            response.ContentType = "image/gif";
            bmp.Save(response.OutputStream, ImageFormat.Gif);
        } else if (ext == "jpg" || ext == "jpeg") {
            response.ContentType = "image/jpeg";
            // 套用 JPEG 品質編碼器參數
            var encoderParams = new EncoderParameters(1);
            encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, (long)thumb.JpegQuality);
            var jpegCodec = ImageCodecInfo.GetImageEncoders().First(c => c.FormatDescription == "JPEG");
            bmp.Save(response.OutputStream, jpegCodec, encoderParams);
        } else {
            response.ContentType = "image/bmp";
            bmp.Save(response.OutputStream, ImageFormat.Bmp);
        }
        bmp.Dispose();
        response.Flush();
        response.End(); // 關鍵:中止後續頁面生命週期
    }

    Bitmap GetThumbnail() {
        Image original;
        try {
            if (DesignMode) original = Properties.Resources.ThumbnailDesign;
            else original = Image.FromFile(Context.Server.MapPath(ImageUrl));
        } catch { return Properties.Resources.GenerateImageError; }

        Size newSize = GetNewSize((int)Width.Value, (int)Height.Value, original.Width, original.Height);
        var outBmp = new Bitmap((int)Width.Value, (int)Height.Value);
        using (var g = Graphics.FromImage(outBmp)) {
            g.CompositingQuality = CompositingQuality.HighQuality;
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.Clear(BackColor);
            var rect = new Rectangle(
                (int)Math.Round((Width.Value - newSize.Width) / 2.0),
                (int)Math.Round((Height.Value - newSize.Height) / 2.0),
                newSize.Width, newSize.Height);
            g.DrawImage(original, rect, 0, 0, original.Width, original.Height, GraphicsUnit.Pixel);
        }
        original.Dispose();
        return outBmp;
    }

    Size GetNewSize(int maxW, int maxH, int w, int h) {
        double ratio = Math.Min((double)maxW / w, (double)maxH / h);
        return new Size((int)(w * ratio), (int)(h * ratio));
    }
}

使用方式

  1. 將編譯後的 DLL 加入工具箱。
  2. 拖曳 Thumbnail 至 .aspx 頁面,設定 ImageUrl、Width、Height、JpegQuality 等屬性。
  3. 執行專案,控制項自動產生縮略圖並顯示。

擴充建議

  • 加入浮水印功能(於 GetThumbnail 中繪製文字/圖形)。
  • 支援快取機制(以 ImageUrl + Width + Height 為 Key 存放 MemoryCache,避免重複運算)。
  • 增加 Mode 屬性:Crop(裁切)、Stretch(拉伸)、Fit(等比縮放,現行預設)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved