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

ASP.NET 圖片動態文字浮水印:GDI+ 繪製與查詢字串參數化

     編輯:ASP.NET 基礎

應用場景

  • 論壇/部落格圖片自動加上「來源網站」或「用戶暱稱」。
  • 防盜連結:動態產生帶水印圖片,原圖不對外直接連結。
  • 個性化圖片:電子郵件行銷、分享卡片自動嵌入收件者姓名。

核心實作 (Generic Handler .ashx 推薦)

使用 `.ashx` 而非 `.aspx` 可避免頁面生命週期開銷,直接輸出二進位圖片流。

Watermark.ashx.cs

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Web;

public class Watermark : IHttpHandler
{
    public bool IsReusable => true;

    public void ProcessRequest(HttpContext context)
    {
        // 1. 參數驗證
        string text = context.Request.QueryString["text"] ?? "Sample";
        if (text.Length > 20) text = text.Substring(0, 20); // 限制長度防止溢出

        string imgPath = context.Server.MapPath("~/Images/base-photo.jpg");
        if (!System.IO.File.Exists(imgPath))
        {
            context.Response.StatusCode = 404;
            return;
        }

        // 2. 載入原圖
        using (Image baseImg = Image.FromFile(imgPath))
        using (Graphics g = Graphics.FromImage(baseImg))
        {
            // 3. 繪圖品質設定
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

            // 4. 字體與筆刷
            using (Font font = new Font("微軟正黑體", 24, FontStyle.Bold, GraphicsUnit.Pixel))
            using (SolidBrush brush = new SolidBrush(Color.FromArgb(180, 255, 255, 255))) // 半透明白
            using (SolidBrush shadowBrush = new SolidBrush(Color.FromArgb(180, 0, 0, 0))) // 陰影
            {
                // 5. 計算位置 (右下角偏移 10px)
                SizeF textSize = g.MeasureString(text, font);
                float x = baseImg.Width - textSize.Width - 10;
                float y = baseImg.Height - textSize.Height - 10;

                // 6. 繪製陰影 (偏移 1px) 增強可讀性
                g.DrawString(text, font, shadowBrush, x + 1, y + 1);
                // 7. 繪製主文字
                g.DrawString(text, font, brush, x, y);
            }

            // 8. 輸出 JPEG (品質 85%)
            var encoderParams = new EncoderParameters(1);
            encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, 85L);
            ImageCodecInfo jpgEncoder = GetEncoderInfo("image/jpeg");

            context.Response.ContentType = "image/jpeg";
            baseImg.Save(context.Response.OutputStream, jpgEncoder, encoderParams);
        }
    }

    private ImageCodecInfo GetEncoderInfo(string mimeType)
    {
        foreach (var codec in ImageCodecInfo.GetImageEncoders())
            if (codec.MimeType == mimeType) return codec;
        return null;
    }
}

Web.config 註冊 (IIS 7+)

<system.webServer>
  <handlers>
    <add name="Watermark" verb="GET" path="Watermark.ashx" type="YourNamespace.Watermark, YourAssembly" preCondition="integratedMode" />
  </handlers>
</system.webServer>

前端調用方式

<!-- 直接用 img 標籤指向 Handler -->
<img src="Watermark.ashx?text=Hello%20World" alt="動態水印圖片" />

<!-- 或在 Razor/WebForms 後端產生 URL -->
<img src="<%= ResolveUrl("~/Watermark.ashx?text=" + Server.UrlEncode(user.Name)) %>" />

進階功能擴充

功能實作要點
多行文字自動換行`StringFormat` 設定 `FormatFlags = StringFormatFlags.LineLimit`,配合 `MeasureString` 計算高度逐行繪製
圖片水印 (Logo)`g.DrawImage(logoImg, x, y, width, height)`,支援 PNG 透明通道
斜向平鋪水印雙重迴圈 `for (int y=-h; y<2*h; y+=step) for (int x=-w; x<2*w; x+=step) g.DrawString(...)` 並 `g.RotateTransform(-30)`
字體自適應縮放依圖片寬度計算 `fontSize = Math.Max(12, img.Width / 30)`
快取輸出`context.Response.Cache.SetMaxAge(TimeSpan.FromDays(30))` + `ETag` 依參數雜湊
防盜連結驗證 `Request.UrlReferrer` 或簽名 Token (HMAC) 過期時間

注意事項與效能優化

  1. GDI+ 非執行緒安全:`Image.FromFile` 鎖定檔案,**務必 `using` 釋放**,否則檔案無法覆寫/刪除。
  2. 記憶體壓力:大量併發產生大圖易觸發 LOH 碎片。建議:
    • 限制輸出尺寸 (如最大 1920px)。
    • 使用 `ArrayPool` 緩衝區 (Core 3.0+)。
    • 考慮 **ImageSharp** (跨平台、純 managed、無 GDI+ 鎖定) 替代 `System.Drawing`。
  3. 字體授權:伺服器需安裝對應字體 (如「微軟正黑體」需 Windows 授權),Linux 容器需複製 `.ttf` 並用 `PrivateFontCollection` 載入。
  4. 編碼問題:QueryString 中文需 `Server.UrlEncode`,Handler 端 `context.Request.QueryString["text"]` 自動解碼。

結語

ASP.NET 搭配 `IHttpHandler` + `System.Drawing` 實作動態文字水印,架構輕量、效能足夠中小流量場景。高併發、跨平台 (Linux Docker) 生產環境,**強烈建議遷移至 ImageSharp + Minimal API**,徹底解決 GDI+ 原生相依與記憶體洩漏風險。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved