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

ASP.NET 圖片上傳與高畫質縮略圖生成實作

     編輯:ASP.NET 基礎

前言

在 ASP.NET Web Forms 專案中,圖片上傳與縮略圖生成是常見需求。許多開發者面臨縮略圖模糊、失真或尺寸過大的問題。本文提供一套完整的上傳與兩階段縮放演算法,能產生接近繪圖軟體品質的高清縮略圖。

核心程式碼實作

/// 
/// ASP.NET 上傳圖片並生成高畫質縮略圖
/// 
/// HtmlInputFile 控制項
/// 相對伺服器儲存路徑
/// 縮略圖檔名前綴
/// 縮略圖寬度
/// 縮略圖高度
/// 縮略圖檔名
public string UpLoadImage(HtmlInputFile upImage, string sSavePath, string sThumbExtension, 
    int intThumbWidth, int intThumbHeight) {
    
    string sThumbFile = "", sFilename = "";
    if (upImage.PostedFile == null) return "未選擇圖片";

    HttpPostedFile myFile = upImage.PostedFile;
    int nFileLen = myFile.ContentLength;
    if (nFileLen == 0) return "未選擇上傳圖片";

    // 驗證副檔名
    string extendName = System.IO.Path.GetExtension(myFile.FileName).ToLower();
    if (extendName != ".jpg" && extendName != ".jpeg" && extendName != ".gif" 
        && extendName != ".bmp" && extendName != ".png")
        return "圖片格式不正確";

    // 讀取檔案位元組
    byte[] myData = new Byte[nFileLen];
    myFile.InputStream.Read(myData, 0, nFileLen);
    sFilename = System.IO.Path.GetFileName(myFile.FileName);

    // 避免同名檔案覆蓋
    int file_append = 0;
    while (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath(sSavePath + sFilename))) {
        file_append++;
        sFilename = System.IO.Path.GetFileNameWithoutExtension(myFile.FileName) 
            + file_append.ToString() + extendName;
    }

    // 儲存原圖
    string fullPath = System.Web.HttpContext.Current.Server.MapPath(sSavePath + sFilename);
    using (var newFile = new System.IO.FileStream(fullPath, System.IO.FileMode.Create, 
        System.IO.FileAccess.Write)) {
        newFile.Write(myData, 0, myData.Length);
    }

    try {
        // === 兩階段縮放演算法 ===
        using (var sourceImage = System.Drawing.Image.FromFile(fullPath)) {
            int width = sourceImage.Width;
            int height = sourceImage.Height;
            int smallWidth, smallHeight;

            // 第一階段:等比例縮放至符合目標長寬比的中間尺寸
            if (((decimal)width) / height <= ((decimal)intThumbWidth) / intThumbHeight) {
                smallWidth = intThumbWidth;
                smallHeight = intThumbWidth * height / width;
            } else {
                smallWidth = intThumbHeight * width / height;
                smallHeight = intThumbHeight;
            }

            // 產生中間圖(高品質插值)
            using (var bitmap = new System.Drawing.Bitmap(smallWidth, smallHeight))
            using (var g = System.Drawing.Graphics.FromImage(bitmap)) {
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                g.Clear(System.Drawing.Color.White);
                g.DrawImage(sourceImage, 
                    new System.Drawing.Rectangle(0, 0, smallWidth, smallHeight),
                    new System.Drawing.Rectangle(0, 0, width, height),
                    System.Drawing.GraphicsUnit.Pixel);
            }

            // 第二階段:從中間圖裁切至目標尺寸(置中裁切)
            file_append = 0;
            sThumbFile = sThumbExtension + System.IO.Path.GetFileNameWithoutExtension(myFile.FileName) + extendName;
            while (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath(sSavePath + sThumbFile))) {
                file_append++;
                sThumbFile = sThumbExtension + System.IO.Path.GetFileNameWithoutExtension(myFile.FileName) 
                    + file_append.ToString() + extendName;
            }

            string smallImagePath = System.Web.HttpContext.Current.Server.MapPath(sSavePath) + sThumbFile;
            using (var bitmap1 = new System.Drawing.Bitmap(intThumbWidth, intThumbHeight))
            using (var g = System.Drawing.Graphics.FromImage(bitmap1)) {
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                g.Clear(System.Drawing.Color.White);

                int lwidth = (smallWidth - intThumbWidth) / 2;
                int bheight = (smallHeight - intThumbHeight) / 2;
                g.DrawImage(bitmap, 
                    new System.Drawing.Rectangle(0, 0, intThumbWidth, intThumbHeight),
                    lwidth, bheight, intThumbWidth, intThumbHeight,
                    System.Drawing.GraphicsUnit.Pixel);

                bitmap1.Save(smallImagePath, System.Drawing.Imaging.ImageFormat.Jpeg);
            }
        }
        return sThumbFile;
    } catch {
        // 發生錯誤時刪除已上傳的原圖
        System.IO.File.Delete(System.Web.HttpContext.Current.Server.MapPath(sSavePath + sFilename));
        return "圖片處理失敗";
    }
}

前端呼叫範例

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" %>


圖片上傳測試

    
protected void Button1_Click(object sender, EventArgs e) {
    string thumbName = this.UpLoadImage(this.File1, "UpLoad/", "thumb_", 118, 118);
    // thumbName 即為生成的縮略圖檔名
}

進階優化建議:多階段漸進式縮放

若原圖極大(如 5000×5000)需縮至極小(100×80),單次縮放易產生鋸齒。可採用多階段漸進縮放:

  1. 原圖 → 3000×3000
  2. 3000×3000 → 1000×1000
  3. 1000×1000 → 100×100(中間圖)
  4. 100×100 → 100×80(最終裁切)

中間圖層數越多,最終畫質越接近專業繪圖軟體輸出效果。

注意事項

  • 生產環境建議加入檔案大小限制、MIME 類型二次驗證
  • 大量上傳場景請考慮非同步處理或雲端儲存
  • System.Drawing 在 .NET Core / Linux 環境下有相容性限制,建議改用 ImageSharp 或 SkiaSharp
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved