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

ASP.NET 圖片不存在時自動顯示默認圖片的三種優雅實現

     編輯:ASP.NET 基礎

場景與痛點

電商商品圖、用戶頭像、文章縮略圖等業務中,數據庫存儲圖片路徑,但文件可能被刪除、遷移失敗、路徑錯誤。頁面直接綁定 ImageUrl 會導致瀏覽器顯示破碎圖標,體驗極差。需要服務端/客戶端自動降級到默認佔位圖。

方案一:服務端綁定時判斷(最可靠,推薦)

web.config 配置默認圖

<appSettings>
  <add key="DefaultImageUrl" value="~/Content/Images/placeholder.png" />
</appSettings>

後端代碼

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack) BindData();
}

private void BindData()
{
    // 假設從數據庫讀取
    var dt = GetDataTable(); // 包含 ImagePath 列
    rptList.DataSource = dt;
    rptList.DataBind();
}

protected void rptList_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
    {
        var img = e.Item.FindControl("imgProduct") as Image;
        var row = e.Item.DataItem as DataRowView;
        string dbPath = row["ImagePath"]?.ToString();

        if (string.IsNullOrWhiteSpace(dbPath) || !FileExists(dbPath))
        {
            img.ImageUrl = ResolveUrl(ConfigurationManager.AppSettings["DefaultImageUrl"]);
        }
        else
        {
            img.ImageUrl = ResolveUrl(dbPath);
        }
    }
}

private bool FileExists(string virtualPath)
{
    // 支持相對路徑 ~/ 或 絕對路徑
    string physical = Server.MapPath(virtualPath);
    return System.IO.File.Exists(physical);
}

方案二:客戶端 JavaScript 兜底(零後端改動,適用靜態頁/前端渲染)

<img src="/images/product/123.jpg" 
     onerror="this.onerror=null; this.src='/Content/Images/placeholder.png';" 
     alt="商品圖片" />

關鍵點:this.onerror=null 防止默認圖也失效時陷入無限循環。

批量綁定:頁面載入後統一掛載

<script>
document.addEventListener('DOMContentLoaded', function() {
    var defaultImg = '/Content/Images/placeholder.png';
    document.querySelectorAll('img[data-fallback]').forEach(function(img) {
        img.onerror = function() {
            if (this.src !== defaultImg) {
                this.onerror = null;
                this.src = defaultImg;
            }
        };
    });
});
</script>

<!-- 頁面中 -->
<img data-fallback="true" src="/images/abc.jpg" />

方案三:自定義 Image 控件封裝(組件化復用)

[ToolboxData("<{0}:SmartImage runat=server />")]
public class SmartImage : Image
{
    public string DefaultImageUrl { get; set; } = "~/Content/Images/placeholder.png";

    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);
        if (!string.IsNullOrEmpty(ImageUrl))
        {
            string physical = Context.Server.MapPath(ImageUrl);
            if (!System.IO.File.Exists(physical))
            {
                ImageUrl = ResolveClientUrl(DefaultImageUrl);
            }
        }
        else
        {
            ImageUrl = ResolveClientUrl(DefaultImageUrl);
        }

        // 同時輸出 onerror 兜底(雙重保險)
        Attributes["onerror"] = $"this.onerror=null; this.src='{ResolveClientUrl(DefaultImageUrl)}';";
    }
}

頁面使用

<%@ Register TagPrefix="cc" Namespace="YourControls" Assembly="YourAssembly" %>
<cc:SmartImage ID="imgAvatar" runat="server" ImageUrl='<%# Eval("AvatarPath") %>' 
    DefaultImageUrl="~/Content/Images/avatar-default.png" />

三種方案對比

維度服務端判斷客戶端 onerror自定義控件
可靠性✅ 最高(文件系統級檢查)⚠️ 僅網絡層面,無法檢測 403/重定向✅ 雙重保障
性能影響每請求一次 File.Exists IO零服務端開銷同方案一 + 少量屬性輸出
適用場景動態數據綁定、嚴格業務靜態頁、前端框架渲染、CDN 圖片項目通用組件庫、長期維護
緩存友好可配合 HttpRuntime.Cache 緩存文件存在性瀏覽器緩存默認圖同方案一

性能優化:緩存文件存在性檢查

private static readonly MemoryCache _fileCache = MemoryCache.Default;

private bool FileExistsCached(string virtualPath)
{
    string key = "FileExist:" + virtualPath;
    if (_fileCache.Contains(key)) return (bool)_fileCache[key];

    bool exists = System.IO.File.Exists(Server.MapPath(virtualPath));
    _fileCache.Add(key, exists, DateTimeOffset.Now.AddMinutes(10)); // 緩存 10 分鐘
    return exists;
}

現代化架構建議

  • 對象存儲 (OSS/S3) + CDN:上傳時同步生成多規格縮略圖,簽名 URL 過期前預簽,彈性處理防盜鏈。
  • 前端框架:Vue ``、React `onError={(e)=>{e.target.src=defaultImg}}`。
  • 佔位圖服務:via.placeholder.com、placehold.co 或自建 /placeholder/{w}x{h} 動態生成 SVG 佔位圖,減少靜態資源維護。

根據項目架構選擇:舊 Web Forms 首選「方案一 + 緩存」;組件化團隊投入「方案三」;前後端分離項目徹底前端化處理。

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