[C#] 解決 GitHub 圖片 429 錯誤:轉換 jsDelivr CDN 網址

GitHub Raw 圖片在單一 Client 短時間大量存取時,可能出現 429 Too Many Requests。本篇記錄如何將 GitHub Raw 與 Blob 圖片網址改寫為 jsDelivr CDN,並提供可直接使用的 C# Function,快速解決既有 Blog 圖片載入與限流問題。

[C#] 解決 GitHub 圖片 429 錯誤:轉換 jsDelivr CDN 網址

最近我遇到一個 GitHub 圖片載入的問題

我習慣把 Blog 使用的一些圖片放在 GitHub Repository,網站直接使用 GitHub Raw URL 顯示圖片

原本一直都正常,但最近在單一 Client 一次讀取比較多圖片時,突然開始出現下面的錯誤

429: Too Many Requests For more on scraping GitHub and how it may affect your rights, please review our Terms of Service

最後我的處理方式很簡單,也是 AI 提示我的 就是改走 jsDelivr CDN 不要讓 Client 直接讀取 GitHub Raw

另外 GitHub 在點擊 Raw 或取得圖片網址時,也可能拿到這種格式:

https://github.com/donma/BlogResource/blob/main/2569/264203.png?raw=true

這兩種網址直接丟到瀏覽器都可以正常顯示圖片

所以一開始我也沒有特別處理

但問題就在於,GitHub Raw 可以讀取圖片,不代表適合直接拿來當網站的圖片 CDN

當同一個 Client 在短時間內載入大量圖片時,就有機會直接收到:

429: Too Many Requests,可能最近因為 vibe coding 問一下 AI 好像再 2025 下半年開始陸續出現這問題..

1. 簡單的說就是改寫網址把網址改成

網址格式如下:

https://cdn.jsdelivr.net/gh/{owner}/{repo}@{branch}/{path}

例如原本:

https://raw.githubusercontent.com/donma/BlogResource/refs/heads/main/2569/0331-03-42.jfif

轉換後:

https://cdn.jsdelivr.net/gh/donma/BlogResource@main/2569/0331-03-42.jfif

另一種 GitHub Blob URL:

https://github.com/donma/BlogResource/blob/main/2569/264203.png?raw=true

轉換後:

https://cdn.jsdelivr.net/gh/donma/BlogResource@main/2569/264203.png

其實規則不複雜。

GitHub Raw:

/{owner}/{repo}/refs/heads/{branch}/{path}

GitHub Blob:

/{owner}/{repo}/blob/{branch}/{path}

最後統一轉成:

/{owner}/{repo}@{branch}/{path}


2. 這邊提供一個 C# function ,之後你就可以無腦使用

using System;
using System.Linq;

public static string ToJsDelivrUrl(string url)
{
    if (string.IsNullOrWhiteSpace(url))
    {
        return url;
    }

    Uri uri;

    if (!Uri.TryCreate(url, UriKind.Absolute, out uri))
    {
        return url;
    }

    string[] segments = uri.AbsolutePath
        .Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);

    string owner;
    string repository;
    string branch;
    string filePath;

    if (uri.Host.Equals(
        "raw.githubusercontent.com",
        StringComparison.OrdinalIgnoreCase))
    {
        if (segments.Length < 4)
        {
            return url;
        }

        owner = segments[0];
        repository = segments[1];

        if (segments.Length >= 6 &&
            segments[2].Equals(
                "refs",
                StringComparison.OrdinalIgnoreCase) &&
            segments[3].Equals(
                "heads",
                StringComparison.OrdinalIgnoreCase))
        {
            branch = segments[4];
            filePath = string.Join("/", segments.Skip(5));
        }
        else
        {
            branch = segments[2];
            filePath = string.Join("/", segments.Skip(3));
        }
    }
    else if (uri.Host.Equals(
        "github.com",
        StringComparison.OrdinalIgnoreCase))
    {
        if (segments.Length < 5 ||
            !segments[2].Equals(
                "blob",
                StringComparison.OrdinalIgnoreCase))
        {
            return url;
        }

        owner = segments[0];
        repository = segments[1];
        branch = segments[3];
        filePath = string.Join("/", segments.Skip(4));
    }
    else
    {
        return url;
    }

    if (string.IsNullOrWhiteSpace(filePath))
    {
        return url;
    }

    return string.Format(
        "https://cdn.jsdelivr.net/gh/{0}/{1}@{2}/{3}",
        owner,
        repository,
        branch,
        filePath);
}


記得加入:

using System;

using System.Linq;

這個 function 目前支援:

https://raw.githubusercontent.com/{owner}/{repo}/refs/heads/{branch}/{path}

https://raw.githubusercontent.com/{owner}/{repo}/{branch}/{path}

以及:

https://github.com/{owner}/{repo}/blob/{branch}/{path}?raw=true

如果不是 Github 圖片網址,就直接回傳原本的 URL

最後說個結論,其實一值把圖片在 Github 上不一定是好事,但是之前就這樣規畫了

所以這目前是一個快速解決的方法,最好的方式還是自己 own 圖片但是就是得自己扛流量

這次遇到 GitHub Raw 回傳 429: Too Many Requests,才發現原本一直可以正常讀取

不代表這個使用方式就適合網站長期使用,改到 jsdelivr 應該是目前最簡單的解法

紀錄一下,給有需要的人