首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >GitHub README 里的图片全裂了:国内服务器的图为什么 GitHub 抓不到,以及一个周刊工具的做法

GitHub README 里的图片全裂了:国内服务器的图为什么 GitHub 抓不到,以及一个周刊工具的做法

原创
作者头像
DN2025
发布于 2026-11-08 19:19:24
发布于 2026-11-08 19:19:24
840
举报

背景

我在做一个产品导航站 Builderoom,每周会把新上架的产品整理成一期周刊,发到一个公开的 GitHub 仓库,借 GitHub 的社区流量做推广。

第一版很简单:Markdown 里的图片直接引用站上的图片地址。发出去一看,图片全部裂开。

原因:GitHub 的图片代理(camo)从海外抓图

GitHub 页面上的外链图片不是浏览器直接去加载的,而是经过 GitHub 自己的图片代理 camo:camo 先从海外去源站抓图,再把图片发给浏览器。

camo 抓国内服务器经常失败。我们实测过几种来源:

图片来源

结果

站点自己的媒体域名

失败

对象存储直连地址

失败

其他几个国内站点的图

失败

所以这不是我们某一台服务器的问题,而是「海外代理抓国内源站」这条链路本身就不稳定。浏览器那一端能不能访问源站并不重要,因为浏览器根本不直接去访问源站。

解决:把图片和这一期的文件一起提交进仓库

图片放进仓库后由 GitHub 自己提供,不经过 camo。页面里用相对路径引用:

代码语言:txt
复制
weekly/
├── docs/issue-003.md               本期正文
├── docs/assets/issue-003/          本期图片
│   ├── some-product-logo.png
│   └── some-product-1.webp
└── README.md                       往期索引
修好之后的周刊页面
修好之后的周刊页面

图片命名用 {slug}-logo、{slug}-{序号},扩展名按下载时响应的 Content-Type 来定,不信任 URL 里的后缀。单张超过 2 MB 的跳过(主要是没有压缩过的 GIF),不让一张动图把仓库撑大。

一期一个 commit:为什么用 Git Data API

一期周刊包含三样东西:本期正文、本期图片、更新后的 README 往期索引。它们必须同时成功或同时失败。

如果用 Contents API,每个文件单独提交一次,中途失败就会留下「有期刊、没索引」或者「有索引、图片缺一半」的半成品。所以改用 Git Data API,自己拼一个 commit:

  1. 读分支最新的 commit,拿到它的 tree
  2. 图片逐张上传为 blob
  3. 以最新 commit 的 tree 为基础,新建一个 tree:加入本期正文、图片、README,同时删掉本期不再用到的旧图片
  4. 新建 commit,父节点是第 1 步的 commit
  5. 以非强制方式更新分支引用

第 5 步很重要。如果这期间分支被别人推进过(比如有人在网页上改了 README),更新会失败,重跑一次即可,不会覆盖别人的提交。用 force: true 省事,但会悄悄吞掉别人的改动。

两个让一期从几分钟缩到一两分钟的细节

图片去重。很多产品每期都会出现 logo,没必要每次都重新上传。按 git hash-object 相同的算法在本地算出 blob 的 SHA,和仓库里已有的比对,相同的直接复用:

代码语言:python
复制
import hashlib

def git_blob_sha(data: bytes) -> str:
    # 与 git hash-object 相同:sha1("blob <长度>\0" + 内容)
    header = f"blob {len(data)}\0".encode()
    return hashlib.sha1(header + data).hexdigest()

主动限速。GitHub 对「产生内容」的请求另有一层限流,大约每分钟不超过 80 次,和普通的 API 限额是两回事。超了会被临时拒绝。所以上传 blob 时每张间隔 0.8 秒,一期几十张图一两分钟就传完了。

凭据只给最小权限

用 fine-grained PAT(细粒度个人访问令牌),只授权周刊这一个仓库,权限只开 Contents: Read and write。工具跑在本机,令牌泄露时影响范围也只有这一个仓库。

往期索引只改标记之间的内容

README 是人维护的,工具不该擅自改结构。所以 README 里用一对注释标记圈出往期列表区:

代码语言:txt
复制
<!-- WEEKLY-INDEX:START -->
- [第 3 期](docs/issue-003.md):2026-10-19 ~ 2026-10-25,收录 30 款作品
<!-- WEEKLY-INDEX:END -->

工具只改标记之间:本期插在最上面;同一期已有就原地替换,不重复插入。标记缺失时直接报错,不自动添加。

先 dry-run 再发

--dry-run 不向 GitHub 写任何东西,把本期文件、图片和更新后的 README 写到本地一个目录,结构和仓库一致,在编辑器里预览就能看到图片。确认没问题再正式发布。

最后

周刊仓库在这里,每周一期,收录当周在 Builderoom 上架的产品:

https://github.com/cena001plus/weekly

Builderoom 是独立开发者、设计师与创客的作品展台,网页应用、小程序、App、浏览器扩展、AI 智能体、API / SDK、设计作品都能收录。提交只要贴一个链接,AI 会把介绍、核心功能、分类标签和截图整理好;每位创作者有自己的主页,集中展示全部作品。

Builderoom 首页
Builderoom 首页

https://www.builderoom.com/zh-CN?utm_source=tencentcloud

你在 GitHub 上遇到过图片加载不出来的问题吗?是怎么解决的?

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 背景
  • 原因:GitHub 的图片代理(camo)从海外抓图
  • 解决:把图片和这一期的文件一起提交进仓库
  • 一期一个 commit:为什么用 Git Data API
  • 两个让一期从几分钟缩到一两分钟的细节
  • 凭据只给最小权限
  • 往期索引只改标记之间的内容
  • 先 dry-run 再发
  • 最后
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档