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

ASP.NET 相簿管理核心類別:PhotoManager 完整實作解析

     編輯:關於C#

簡介

本文解析一個精簡且功能完整的 ASP.NET 相簿管理核心類別 PhotoManager,涵蓋相片/相簿的 CRUD、權限控制、縮圖產生、批次上傳列表等實用功能。程式碼採用 ADO.NET 執行預存程序,搭配 System.Drawing 進行影像處理,是中小型相簿系統的優良參考架構。

類別架構概覽

  • 資料存取:所有方法使用 SqlConnection/SqlCommand 呼叫預存程序,參數化查詢防止 SQL Injection。
  • 權限模型:依據 HttpContext.Current.User.IsInRole("Friends") 或 "Administrators" 決定是否過濾私有內容。
  • 影像處理:ResizeImageFile 依指定長邊等比縮放,支援 Small(100px)、Medium(200px)、Large(600px) 三種尺寸。
  • 資料傳輸物件:Photo、Album、PhotoSize 等簡單 POCO 類別(程式碼中未列出,需自行定義)。

核心方法解析

1. 取得相片串流

public static Stream GetPhoto(int photoid, PhotoSize size)
{
    using (SqlConnection conn = new SqlConnection(ConnString))
    using (SqlCommand cmd = new SqlCommand("GetPhoto", conn))
    {
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.Add(new SqlParameter("@PhotoID", photoid));
        cmd.Parameters.Add(new SqlParameter("@Size", (int)size));
        bool filter = !(HttpContext.Current.User.IsInRole("Friends") || HttpContext.Current.User.IsInRole("Administrators"));
        cmd.Parameters.Add(new SqlParameter("@IsPublic", filter));
        conn.Open();
        object result = cmd.ExecuteScalar();
        try { return new MemoryStream((byte[])result); }
        catch { return null; }
    }
}

重點:回傳 MemoryStream 讓呼叫端直接輸出至 Response 或繫結至 Image 控制項;若查無資料或轉型失敗回傳 null。

2. 新增相片(含自動產生三種尺寸)

public static void AddPhoto(int AlbumID, string Caption, byte[] BytesOriginal)
{
    using (SqlConnection conn = new SqlConnection(ConnString))
    using (SqlCommand cmd = new SqlCommand("AddPhoto", conn))
    {
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.Add(new SqlParameter("@AlbumID", AlbumID));
        cmd.Parameters.Add(new SqlParameter("@Caption", Caption));
        cmd.Parameters.Add(new SqlParameter("@BytesOriginal", BytesOriginal));
        cmd.Parameters.Add(new SqlParameter("@BytesFull", ResizeImageFile(BytesOriginal, 600)));
        cmd.Parameters.Add(new SqlParameter("@BytesPoster", ResizeImageFile(BytesOriginal, 198)));
        cmd.Parameters.Add(new SqlParameter("@BytesThumb", ResizeImageFile(BytesOriginal, 100)));
        conn.Open();
        cmd.ExecuteNonQuery();
    }
}

設計亮點:一次上傳原始圖,伺服器端同步產生三種尺寸儲存,前端可依裝置需求請求不同解析度,減少頻寬浪費。

3. 影像縮放核心邏輯


private static byte[] ResizeImageFile(byte[] imageFile, int targetSize)
{
    using (Image oldImage = Image.FromStream(new MemoryStream(imageFile)))
    {
        Size newSize = CalculateDimensions(oldImage.Size, targetSize);
        using (Bitmap newImage = new Bitmap(newSize.Width, newSize.Height, PixelFormat.Format24bppRgb))
        using (Graphics canvas = Graphics.FromImage(newImage))
        {
            canvas.SmoothingMode = SmoothingMode.AntiAlias;
            canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;
            canvas.PixelOffsetMode = PixelOffsetMode.HighQuality;
            canvas.DrawImage(oldImage, new Rectangle(new Point(0, 0), newSize));
            MemoryStream ms = new MemoryStream();
            newImage.Save(ms, ImageFormat.Jpeg);
            return ms.GetBuffer();
        }
    }
}

private static Size CalculateDimensions(Size oldSize, int targetSize)
{
    Size newSize = new Size();
    if (oldSize.Height > oldSize.Width)
    {
        newSize.Width = (int)(oldSize.Width * ((float)targetSize / oldSize.Height));
        newSize.Height = targetSize;
    }
    else
    {
        newSize.Width = targetSize;
        newSize.Height = (int)(oldSize.Height * ((float)targetSize / oldSize.Width));
    }
    return newSize;
}

採用高品質雙三次插值,保持長寬比,輸出 JPEG 格式位元組陣列,適合直接寫入資料庫 BLOB 欄位。

4. 相簿管理與隨機推薦

  • GetAlbums()、AddAlbum()、EditAlbum()、RemoveAlbum():標準 CRUD,同樣套用權限過濾。
  • GetRandomAlbumID():從非空相簿中隨機挑選,供首頁推薦使用。

5. 批次上傳輔助

public static ICollection ListUploadDirectory()
{
    DirectoryInfo d = new DirectoryInfo(HttpContext.Current.Server.MapPath("~/Upload"));
    return d.GetFileSystemInfos("*.jpg");
}

列出伺服器 /Upload 目錄下所有 JPG,供批次上傳介面預覽。

資料庫預存程序需求

程式碼假設資料庫已建立以下預存程序(需自行實作):

  • GetPhoto, GetFirstPhoto, GetPhotos, AddPhoto, RemovePhoto, EditPhoto
  • GetAlbums, AddAlbum, RemoveAlbum, EditAlbum, GetNonEmptyAlbums

資料表建議欄位:Albums(AlbumID, Caption, IsPublic, NumberOfPhotos)、Photos(PhotoID, AlbumID, Caption, BytesOriginal, BytesFull, BytesPoster, BytesThumb, IsPublic)。

安全與效能建議

  1. 連接字串外部化:將 ConnString 移至 web.config <connectionStrings>,避免硬編碼。
  2. 使用連接池:連接字串已含 pooling=true,確保高併發效能。
  3. 大檔案串流處理:若原始圖極大,建議改用 SqlFileStream (Filestream) 或物件儲存,避免記憶體壓力。
  4. 錯誤處理與日誌:目前 catch 僅回傳 null/吞噬例外,生產環境應記錄錯誤並拋出自訂例外。

結語

PhotoManager 展示了以 ADO.NET + 預存程序 + GDI+ 打造相簿核心邏輯的經典模式。雖然現代開發傾向 ORM (EF Core) 與雲端儲存,但理解這層基礎實作有助於在受限環境(無 NuGet、舊版 .NET)下快速交付,也是學習影像處理與資料存取整合的優良教材。

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