1. 为什么我用 GitHub 当图床:需求拆解与方案选型
写 Markdown 的人迟早会撞上同一个问题:本地截图往编辑器里一粘,预览看着挺好,一发到博客、笔记软件或者项目文档里,图片全变成一个个裂开的图标。原因很简单,本地路径./images/demo.png只在你自己的硬盘上成立,换台设备、换个平台,它就什么都不是。图床这个词听着玄乎,说白了就是"把图片放到一个公网能访问的地方,拿到一条固定的外链,用这条链接代替本地路径"。而 GitHub 图床,就是拿 GitHub 的仓库当这个存储空间,靠仓库的公开访问能力把图片暴露出去。这套方案我在自己的 Hexo 博客和几份长期维护的文档里用了三年多,零成本、可追溯、能版本回滚,对我来说性价比相当高。这篇东西写给三类人:刚接触 Markdown 想给博客配图的新手、被第三方图床跑路坑过一次的老玩家,以及想把图片资产管理得稍微正规一点的独立开发者。下面从选型逻辑一路讲到踩坑排查,全部是我自己跑过的路径。
1.1 图床到底帮你解决了什么
先把这个概念彻底说透,不然后面的选型判断你会没有依据。图床的本质是存储加外链这两件事的组合:存储负责把文件放住,外链负责让别的地方能引用。传统做法是把图片和文章放在一起,跟着项目走,这在单机写作时完全没问题,但一旦涉及多端同步、多平台分发,立刻崩盘。我自己遇到的第一个真实场景是博客:文章 Markdown 存在一台机器上,图片放在source/images里,结果换电脑写作时忘了同步图片目录,推上去的文章图片全部 404,一篇几千字的教程直接废掉。
图床解决的正是这个"耦合"问题。图片上传到一个公共空间,拿到形如https://xxx/2025/06/demo.png的链接,这条链接写进 Markdown 之后,文章本身变成一个自包含的纯文本文件,你把它复制到任何地方——博客、公众号草稿、Issue、给同事的邮件——图片都能正常显示。这是核心价值,也是所有图床方案共同要满足的第一需求。
第二个价值是编辑体验。用图床之后,写作流程会被压缩成"截图 → 快捷键上传 → 剪贴板自动变成外链 → 粘贴",整个过程两三秒,不用手动存文件、不用管命名冲突。这个体验提升对高频写作者来说非常关键,因为一旦流程超过十秒,人就会开始偷懒,最后变成文章里全是"(此处应有图)"。
第三个价值是可迁移性。图片链接是纯文本,只要链接本身长期有效,你的文章就永远不依赖某个特定平台。这一点在选型时权重极高,后面会展开。
1.2 三种主流方案横着比一遍
图床方案粗略分三大类:商业对象存储、自建服务器、代码托管仓库。我把它们放在同一张表里对比,这张表是我当年选型时反复推敲后定下来的判断依据。
| 维度 | 商业对象存储 | 自建服务器 | GitHub 仓库 |
|---|---|---|---|
| 初期成本 | 低(有免费额度) | 高(服务器+域名+人力) | 零 |
| 长期成本 | 按量计费,流量大时明显 | 固定月费,闲置也花钱 | 零(有软性限制) |
| 上传体验 | 官方 SDK 成熟,工具支持好 | 需要自己写接口 | 工具生态好,PicGo 直接支持 |
| 数据掌控 | 在别人手里 | 完全自己掌控 | 在别人手里,但可完整克隆 |
| 版本管理 | 基本没有 | 看你怎么做 | 原生支持,每次上传都是一次 commit |
| 可用性风险 | 欠费即停,敏感内容会被清理 | 服务器到期、磁盘满、欠费 | 仓库违规被限制,或超过容量阈值 |
| 迁移难度 | 中(要批量导出) | 低(数据在自己手上) | 低(git clone 一把梭) |
这张表里最值得说的是可用性风险这一行。很多人选图床只看"免费不免费",忽略了一个关键事实:图床一旦失效,你所有历史文章的图片会同时挂掉,而且是批量挂掉,那种感觉就像家里所有灯泡一起烧了。所以我判断图床方案的标准不是"最便宜",而是"失效时我能不能带走数据"。GitHub 仓库在这一点上得分很高,因为整个仓库就是一个完整的 git 仓库,克隆下来就是全量备份,连历史版本都在。
还有一行是"版本管理",这在其他方案里基本是空白。GitHub 仓库每上传一张图片就是一次 commit,意味着你误删了某张图,可以精确恢复到删除前的状态;你上传了一张有问题的图(比如带隐私信息的截图),也能从历史里彻底清掉。这种能力在写技术文档时特别有用——文档里的截图经常需要更新,旧版本留着反而方便对照。
1.3 GitHub 方案的真实边界,别把它当成无限仓库
讲优点的时候必须把限制讲透,不然你用到一半会很难受。GitHub 免费账号的仓库在容量上有明确的软性边界:单个文件不能超过 100MB,网页端拖拽上传时单个文件限制在 25MB,仓库整体建议控制在 1GB 以内,超过 5GB 会收到平台的容量提醒。这些数字不是我编的,是官方文档里的明确表述。对图床用途来说,100MB 的单文件限制完全够用——一张正常压缩过的网页配图通常在 100KB 到 500KB 之间,一张高清截图撑死 2MB。
真正需要警惕的是仓库体积膨胀。图片是二进制文件,git 对二进制的处理效率远低于文本,而且每次修改都会产生一个新版本存进历史。假如你习惯性地上传一张图、删掉、再传一张改过的,历史里会同时保留两个完整文件。三年下来,一个看起来只有 300 张图的仓库,实际体积可能到 2GB 以上。我在第二年就遇到过这个坑,清理历史花了整整一个下午,后面会专门讲怎么处理。
另一个必须说清楚的边界是公开性。用 GitHub 仓库做图床,仓库必须是公开的,意味着任何人拿到链接都能看到你的图片,也能翻你的仓库目录。所以有几类图片绝对不要往上放:含个人证件、订单号、手机号、住址的截图;公司内部系统的界面截图;有明确版权归属且未获授权的素材。这不是平台规则问题,是你自己该有的基本习惯。上传前用系统自带的截图工具把敏感区域涂掉,或者干脆换一张示意图,这个动作花不了十秒。
2. 动手之前的准备:账号、仓库与目录结构
准备工作看着琐碎,但这一步做对了,后面能省掉大量返工。我见过太多人图快,仓库随手起个名字、图片全部堆在根目录,半年后打开仓库自己都找不到东西在哪里。下面这几点是我自己踩过坑之后固定下来的做法。
2.1 建仓库时三个参数别乱选
新建仓库的页面上有三个选项容易选错,逐个说。
第一是仓库可见性,必须选 Public。私有仓库的 raw 链接需要携带访问凭证,没法直接用在 Markdown 里,做图床等于白做。这一点很多人第一步就走偏,建完私有仓库折腾半天发现图片加载不出来。
第二是是否初始化 README。建议勾上,因为它会顺手创建 main 分支。如果你不勾,仓库建完是空仓库,此时推送代码需要一个初始提交,对不熟悉 git 的人来说容易卡住。勾上 README 之后仓库立刻处于可用状态,省事。
第三是仓库名。名字随你,但我建议带一点语义,比如img-bed或者blog-assets,以后你在别人的配置文件里看到这个仓库名,一眼就知道它是干什么的。别用test、aaa这种,过半年你自己都要猜。
建完之后记下两个信息:用户名和仓库名,后面所有配置都要用到,格式是用户名/仓库名。
2.2 目录结构决定你半年后会不会想重来
这是我认为整个搭建流程里最容易被低估的一步。图片全部堆在根目录会发生什么?第一,仓库首页打开是几百个文件名,找东西靠肉眼扫描;第二,不同文章的同名图片会冲突,demo.png上传第二遍就直接覆盖第一张,而你往往不会及时发现;第三,将来想批量处理某一个时间段或某一个主题的图片时无从下手。
我现在的目录方案是按主题分一级、按年月分二级:
images/ ├── blog/ │ ├── 2024-03/ │ │ └── gh-pages-01.png │ └── 2024-06/ │ └── picgo-config-01.png ├── notes/ │ └── 2025-01/ │ └── sql-index-01.png └── misc/ └── 2025-06/ └── screenshot-01.png这样做有三个好处。第一,物理隔离,不同主题、不同月份的图片永远不会重名冲突,因为路径天然不同。第二,可批量操作,要做格式转换或者清理时,直接针对某个目录跑一条命令就行。第三,便于迁移,将来如果你要把某一部分图片搬到别的图床,只需要处理对应的子目录。
命名上我坚持两条:全小写英文加短横线,不用中文、不用空格、不用大写字母。中文文件名在某些场景下会被转义成一长串百分号编码,链接会变得又丑又容易出错;空格在 Markdown 的链接语法里需要转义,也是麻烦源头。至于加不加随机后缀,看你的工具,PicGo 支持按时间戳自动命名,我一般开着,因为时间戳能天然避免重名,代价是可读性差一点,但图床的链接本来也没人会去读。
2.3 本地工具链准备
纯网页操作也能做图床,但效率太低,建议至少装一个 git 客户端。命令行用户直接用系统自带的 git,Windows 用户如果不想碰命令行,装 GitHub Desktop 完全够用,图形界面上传图片就是把文件拖进去然后点提交。
需要提前配置的只有两行:
git config --global user.name "你的名字" git config --global user.email "你的邮箱"这两行决定了你每次提交时记录的作者信息,跟图床功能无关,但提交历史上会显示,建议填个正常的名字。
另外建议准备一个图片压缩工具。图片体积直接决定加载速度和仓库膨胀速度,我实测下来,同样的截图,用无损压缩工具过一遍能小 30%,转成 WebP 格式能小 60% 到 70%。Squoosh 是一个网页版工具,拖进去选好质量参数下载就行;命令行党用 ImageMagick 的mogrify -strip -quality 82一条命令批量处理整个目录。这一步千万别省,你现在省下的十秒钟,将来会变成几 GB 的仓库和一堆加载缓慢的文章页面。
3. 三种落地路径实测:从纯手动到全自动
准备工作做完,接下来是真正把图片传上去。我把上手难度从低到高排了三条路径,你可以根据自己的使用频率选,也可以先手动跑一遍理解原理,再上自动化工具。
3.1 纯手动:网页拖拽加手拼链接
这条路径一次都不用装软件,适合偶尔传一两张图的人,也适合第一次搭建时用来验证仓库配置是否正确。
操作步骤:打开你的仓库页面,进入你要放图片的目录,点Add file菜单里的Upload files,把图片拖进虚线框,等进度条走完,在下方填写提交信息(比如"add 2025-06 blog images"),点Commit changes。上传完成后点击图片文件,页面上会显示预览,右键选择"复制图片地址",就能拿到链接。
注意事项:这里复制到的链接格式是https://github.com/用户名/仓库名/blob/main/路径/文件名,注意中间是blob,这个链接是 GitHub 的网页预览页,不是图片直链。图片直链要把github.com换成raw.githubusercontent.com,同时把blob换成refs/heads:
https://raw.githubusercontent.com/用户名/仓库名/refs/heads/main/images/2025-06/demo.png或者用短格式,把blob直接换成raw,也能访问:
https://raw.githubusercontent.com/用户名/仓库名/main/images/2025-06/demo.png这两种写法我都用过,日常更推荐短格式,因为短、易读、方便手改。手拼链接虽然笨,但胜在你对链接结构有完全的掌控,后面遇到 404 时排查思路会清晰很多,不会出现"工具帮我做了什么我都不知道"的情况。
3.2 半自动:PicGo 配置要点与 Token 最小权限
这是绝大多数人的最终方案。PicGo 是一个开源的图片上传工具,支持把剪贴板里的图片一键传到 GitHub 并把链接自动写回剪贴板。它的配置里有一个关键步骤容易被做错——访问令牌的权限范围。
先说令牌怎么拿。打开 GitHub 的设置页,找到 Developer settings 里的 Personal access tokens,我建议用 Fine-grained tokens 这种细粒度令牌,因为它可以精确指定"只允许访问某一个仓库"。创建时选好过期时间(我一般设 90 天,到期换新,比永不过期的安全),Repository access 选Only select repositories,勾上你的图床仓库。权限部分只需要给Contents 的 Read and write,其他一律不给。这一步很多人直接勾了repo全权限,那是粗粒度令牌的做法,范围太大,一旦令牌泄露,别人可以动你所有仓库,风险完全没必要承担。
拿到令牌后,在 PicGo 的图床设置里选 GitHub,填这几个字段:
| 配置项 | 填什么 | 说明 |
|---|---|---|
| 仓库名 | 用户名/仓库名 | 中间的斜杠不能少,也不能有空格 |
| 分支名 | main | 老仓库可能是master,去仓库首页确认 |
| Token | 刚才生成的令牌 | 粘贴后不要再动,末尾不要带空格 |
| 存储路径 | images/blog/2025-06/ | 末尾的斜杠建议保留 |
| 自定义域名 | 留空先用 raw 直链 | 后面配 CDN 时再填 |
| 设定仓库名格式 | 保持默认 | 影响不大 |
实测心得:填完之后点"设为默认图床",然后上传一张测试图。如果提示 404,八成是仓库名写错或者令牌没给 Contents 权限;如果提示 401,基本就是令牌粘贴时多带了空格,很多编辑器复制粘贴会带尾随换行,这个坑我踩过两次,排查时先看这里。
还有一个细节值得说:PicGo 的"存储路径"字段支持时间变量,写成images/{yyyy}-{MM}/的话,它会自动按当前年月建目录,你不用手动改。这个功能配合前面讲的目录结构,基本可以做到"上传即归档"。
3.3 命令行批量上传:Contents API 脚本
如果你需要一次传几十张图,或者想把上传集成到构建流程里,用 API 比点鼠标快得多。GitHub 提供了一个 Contents API,允许通过 HTTP 请求创建文件。
#!/usr/bin/env bash # upload.sh - 批量上传当前目录下的 png/jpg 到指定仓库 set -euo pipefail GH_TOKEN="你的令牌" OWNER="用户名" REPO="仓库名" BRANCH="main" REMOTE_DIR="images/blog/2025-06" for f in *.png *.jpg *.jpeg; do [ -e "$f" ] || continue name="$(basename "$f")" content="$(base64 -w0 "$f")" body=$(jq -n \ --arg msg "upload $name" \ --arg c "$content" \ --arg b "$BRANCH" \ '{message:$msg, content:$c, branch:$b}') curl -sS -X PUT \ -H "Authorization: Bearer $GH_TOKEN" \ -H "Accept: application/vnd.github+json" \ "https://api.github.com/repos/$OWNER/$REPO/contents/$REMOTE_DIR/$name" \ -d "$body" > /dev/null echo "uploaded: $REMOTE_DIR/$name" done这段脚本我用了很久,要注意三个点。第一,base64 -w0里的-w0是必须的,不加的话 base64 输出会按 76 字符换行,JSON 会解析失败,这个错误提示很不直观,容易卡半天。第二,用jq拼 JSON 是为了避免文件名里有特殊字符时手动转义出错,如果系统没装 jq,用sudo apt install jq或brew install jq装上。第三,如果同名文件已存在,这个接口会报 422,需要先取文件的sha再带上去做更新,脚本里我没处理这种情况,因为图床场景下重名本来就应该避免,配合时间戳命名基本不会撞上。
3.4 全自动:用 Actions 给图片做压缩归档
上传之后还有一个隐藏的成本:图片是原图,体积偏大。可以挂一个 GitHub Actions 工作流,在图片推上来之后自动压缩一遍,压缩结果直接提交回仓库。
name: optimize-images on: push: paths: - 'images/**' permissions: contents: write jobs: compress: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install ImageMagick run: sudo apt-get update && sudo apt-get install -y imagemagick - name: Compress PNG and JPEG run: | find images -type f \( -iname '*.png' -o -iname '*.jpg' -o -iname '*.jpeg' \) \ -exec mogrify -strip -quality 82 -resize '1920x1920>' {} \; - name: Commit changes run: | git config user.name "img-bot" git config user.email "img-bot@users.noreply.github.com" if [ -n "$(git status --porcelain)" ]; then git add -A git commit -m "chore: optimize images [skip ci]" git push else echo "nothing to commit" fi这段配置里有三个关键设计,值得单独解释。permissions: contents: write是必须的,GitHub 从某个版本起默认给 Actions 的令牌只有只读权限,不显式声明写权限,最后一步推送会直接失败。[skip ci]这个标记写在提交信息里,作用是阻止压缩提交再次触发自身,否则会陷入无限循环——机器人提交 → 触发工作流 → 又提交,很快就把你的 Actions 额度耗光。if [ -n "$(git status --porcelain)" ]是为了避免没有变化时执行空提交,空提交会报错中断工作流,虽然不影响功能,但每次看到红色的失败标记心里不舒服。
-resize '1920x1920>'里的>符号表示"只在图片大于这个尺寸时缩小",小图不会被放大。1920 这个数字是我权衡后的选择:绝大多数显示场景(博客正文、文档、聊天分享)宽度不会超过 1400 像素,1920 留了余量,同时能把手机截的长图从四五兆压到几百 KB。
4. 链接加速与失效排查
图片传上去了,链接也能打开,但你会发现一个问题:raw.githubusercontent.com这个域名在国内访问时快时慢,有时候一张图要转好几秒才出来,博客页面整体加载体验很差。这一节讲怎么处理,以及链接失效时怎么排查。
4.1 raw 直链为什么慢,CDN 换法怎么用
raw.githubusercontent.com是 GitHub 用来分发仓库原始文件的域名,本身没有针对国内做节点优化,所以响应时间波动很大。解决思路很简单:把图片文件交给一个在国内有节点的内容分发网络,让它来扛流量。图片是静态文件,天然适合这种做法。
最常用的选择是 jsDelivr,它对公开的代码仓库提供免费的静态资源分发,链接格式是这样:
https://cdn.jsdelivr.net/gh/用户名/仓库名@分支名/images/2025-06/demo.png注意几个细节。路径部分是gh/用户名/仓库名@分支名/文件路径,gh是它区分代码托管平台的标识,不能省。@分支名那一段是可选的,不写默认走默认分支,但我强烈建议写上,因为显式指定分支之后,你切分支或者默认分支变动时,链接不会莫名其妙失效。如果想锁定某个具体的提交,可以把分支名换成 commit 的短哈希,链接就变成永久不变的了——这个做法适合那种"发出去就不打算改"的正式文档。
在 PicGo 里,把"自定义域名"填成https://cdn.jsdelivr.net/gh/用户名/仓库名@main,之后上传的图片链接会自动带上这个前缀,不用手动替换。
需要知道的限制:jsDelivr 对单个文件有体积门槛,官方给的上限在 20MB 量级,超过就不提供服务。另外它对仓库整体体积也比较敏感,如果你那个仓库膨胀到几 GB,它有可能会拒绝分发。所以前面反复强调的"控制图片体积"在这里体现出了价值——不是洁癖,是实实在在影响可用性。
除了 jsDelivr,也可以自己做更进一步的优化,比如在博客的构建流程里把图片链接统一替换成 CDN 域名,或者给图片加上loading="lazy"属性做懒加载。这两件事都跟图床本身无关,但对页面加载速度的影响比换 CDN 还大,顺手做掉收益很高。
4.2 404 和 403 速查表
图片突然打不开是最常见的问题,绝大多数原因就那么几个。我把排查过的情形整理成表,按出现频率排序。
| 现象 | 最可能的原因 | 排查动作 |
|---|---|---|
| 404 Not Found | 文件名或路径大小写不一致 | 去仓库里逐字符比对路径,Linux 下大小写敏感 |
| 404 Not Found | 分支名写错(main 写成 master) | 打开仓库首页,看分支下拉框显示的名字 |
| 404 Not Found | 用了blob链接而不是raw链接 | 检查 URL 里是否还留着blob |
| 403 Forbidden | 仓库是私有的 | 仓库设置里改成 Public |
| 403 Forbidden | 令牌权限不足或已过期 | 重新生成令牌并更新 PicGo 配置 |
| 图片显示成一段文字 | 链接指向的是网页预览而非文件 | 换成 raw 或 CDN 域名 |
| 链接能开但博客里空白 | 页面使用了 https 而链接是 http | 全部统一成 https |
| 上传报 422 | 仓库里已存在同名文件 | 换文件名或先删除旧文件 |
| 图片偶尔加载失败 | CDN 节点缓存未生效或限流 | 换回 raw 链接对比,确认是 CDN 侧问题 |
这张表里最值得展开的是大小写问题。Windows 和 macOS 的文件系统默认不区分大小写,所以你在本地看Demo.PNG和demo.png感觉没差别,但 GitHub 的服务器是区分大小写的,一旦链接里的大小写和实际文件名不一致,立刻 404。我遇到过最诡异的一次是图片上传后能显示,过了一天打不开,查了半天才发现是重命名时只改了大写字母,git 根本没记录这次改动。
403 那个情形也需要特别注意。如果你把图床仓库从 public 改成了 private(比如临时想保密),那么所有历史文章的图片会同时失效,而且是静默失效——除非有人告诉你,你根本不知道。所以仓库可见性这个开关,改之前一定想清楚。
4.3 缓存和历史遗留导致的怪问题
有一类问题特别迷惑人:图片明明删了或者改名了,访问旧链接还能打开。这是 CDN 缓存在起作用。jsDelivr 这类服务会把文件缓存到边缘节点,缓存时间可能长达数天甚至更久,你更新了仓库内容,节点上还是旧版本。
处理办法有两个。一是主动刷新,jsDelivr 提供了刷新入口,在链接前面加上purge路径访问一次即可请求刷新缓存。二是绕过缓存,在链接末尾加一个查询参数,比如?v=2,因为 CDN 的缓存键包含查询串,加了参数就相当于换了一个新资源。这个技巧在做版本迭代时很实用——你更新了文章里的某张截图,直接给链接加个?v=2,所有读者的浏览器和 CDN 都会重新拉取,不用等缓存过期。
另一种历史遗留问题是误删图片。Git 的好处在这里体现出来:即使你删了文件并提交,历史里还有完整记录。恢复方式是在本地克隆仓库,用git log --diff-filter=D --name-only找出删除该文件的提交,然后在那个提交的前一个版本里把文件取出来:
git checkout <提交哈希>^ -- images/2025-06/demo.png取出来之后重新提交一次,图片就回来了。注意:如果删除操作发生得很久以前,仓库历史很长,这个操作会比较慢,所以还是建议平时做基础备份。
5. 长期维护:容量、备份与迁移
图床这种东西,搭建起来只要半小时,真正花时间的是后面的维护。我用了三年多,总结出几条必须做的动作。
5.1 仓库体积控制与历史清理
先学会查体积。本地克隆仓库后在根目录执行du -sh .git,这个数字是 git 历史占用的空间,往往比工作目录大得多。如果发现.git目录体积明显异常,说明历史里堆积了大量被删掉的图片。
处理方式有两种,按代价从低到高。第一种是浅克隆加新建仓库:如果历史记录对你没价值,直接建一个新仓库,把当前工作目录的文件拷过去推上去,老仓库归档或者删掉,这是最省事的做法,代价是丢失所有提交历史。第二种是历史重写:用git filter-repo这类工具把历史中的大文件剔除,保留提交记录,但这个操作会改变所有提交哈希,属于破坏性操作,执行前必须完整备份,而且不要在共享仓库上随便用。
我更推荐的做法是从源头控制。上传前统一压缩,单张图控制在 500KB 以内;不用手机原图直接传,先在本地过一遍压缩;定期检查仓库体积,发现有几百 KB 以上的大图就处理掉。这套习惯坚持下来,我那个用了三年的图床仓库到现在才 400MB 出头。
5.2 备份与迁移预案
任何依赖单一平台的方案都要想清楚"平台不用了怎么办"。GitHub 图床在这件事上有个天然优势:你的数据是完整的 git 仓库,克隆下来就是全量备份。我给自己定的规矩是每季度克隆一次到本地移动硬盘,成本几秒钟,心里踏实。
迁移到别处也不难,因为你的文章里存的都是完整 URL,只要有工具能做批量替换就行。真要做迁移,步骤大概是这样:把仓库克隆到本地;把图片上传到新图床,同时记录新旧路径的对应关系;用批量替换工具(比如sed或者编辑器的全局替换)把文章里所有旧域名替换成新域名;推上去验证。关键前提是你的域名替换是精确的,如果新旧路径结构不一致,替换就会出错,所以前面强调的"URL 里带完整路径"其实是在为将来迁移铺路。
我建议你至少准备两个备选方案。一个是可以直接切入的备用 CDN,比如同时用两个分发服务的域名,主域名出问题时能快速切换;另一个是完全不同的图床类型,比如对象存储,万一整个路子走不通可以直接搬。这两条都不用真的部署,想清楚流程、写在笔记里就够了。
5.3 每月花十分钟做的检查
维护图床不需要天天盯着,但有几件事值得定期过一遍,我固定成一个月一次:
- 随便抽三篇历史文章,打开看图片是否正常加载,早发现 404 早处理
- 看仓库体积有没有异常增长,
du -sh .git对比上月 - 检查访问令牌的过期时间,快到期就提前换,别等它失效再折腾
- 看仓库里有没有误传的敏感截图,有的话从历史里清掉
- 确认 CDN 域名还能正常访问,必要时刷新缓存
这套动作加起来不到十分钟,但能避免绝大多数"某天突然发现所有图都挂了"的惨剧。我自己就有过一次教训:某篇文章里的三十多张图全部失效,读者在评论区问了三天我才发现,原因是那篇文章用的链接格式还是早期的blob写法,而平台改过一次重定向规则。从那以后我就养成了定期抽查的习惯。
6. 踩坑实录与常见问题
前面讲了很多"应该怎么做",这一节讲"实际会出什么岔子"。这些都是我自己或者身边的人真实遇到的问题,比文档里的说明更接近实际情况。
6.1 我踩过的几个坑
第一个坑是仓库体积失控。刚开始用的时候我完全没有压缩概念,手机截图、录屏截帧直接往上传,一张图五六兆。半年后发现克隆仓库要等好几分钟,一看.git目录已经 1.8GB。处理方式是新建了一个仓库,只把当前需要的图片移过去,老仓库留作归档。这次经历之后我给自己定了硬规矩:上传前一定过一遍压缩,压缩后超过 1MB 的图片要单独确认是否真的需要。
第二个坑是令牌泄露。早期我把令牌直接写在一个公开的脚本文件里传到了仓库,虽然是个临时测试仓库,但还是惊出一身冷汗。现在我的做法是:令牌一律通过环境变量注入,绝不硬编码在文件里;GitHub 提交前用git diff --cached扫一眼,确认没有意外内容;如果真泄露了,立刻去设置页删除那个令牌,重新生成一个。删除之后旧令牌立刻失效,这一步是必须做的,光删文件是没用的,因为它已经进了历史记录。
第三个坑是链接格式不统一。我的文章跨越了好几年,早期用blob链接,中期用raw链接,后面才是 CDN 链接。三种格式混在一起,出现问题时排查思路会被打断。后来我做了一次全局梳理,把所有链接统一成带分支名的 CDN 格式,世界清静了。如果你现在正在起头,建议一开始就定好一种格式,从此不要再变。
第四个坑是关于压缩质量的。有一段时间我把压缩质量设得太激进,截图里的代码文字边缘出现了明显的锯齿和色块,在手机上看小字很吃力。后来把 JPEG 质量从 65 提到 82,PNG 保持无损压缩,观感立刻不一样。质量参数不是越小越好,尤其是技术文档里的代码截图,文字边缘的抗锯齿信息一旦被破坏,可读性下降得很明显。
6.2 新手最容易卡住的问题清单
| 问题 | 根本原因 | 处理办法 |
|---|---|---|
| 网页上传图片失败,提示文件过大 | 网页端单文件限制较严 | 先压缩,或改用 git 命令行推送 |
| git push 报错缺少权限 | 用的是只读令牌或没配置认证 | 检查令牌权限,确认包含 Contents 写权限 |
| 图片在编辑器里能预览,Push 后 404 | 本地路径没上传,或大小写不一致 | 检查仓库里的实际路径 |
| PicGo 上传成功但图片不显示 | 用了网页预览链接而不是直链 | 复制链接时手动改域名 |
| 换电脑后工具配置全丢 | 配置只存在本地 | 定期导出 PicGo 配置文件备份 |
| 同一张图反复上传产生多个副本 | 工具没有按内容去重 | 用固定命名规则,上传前检查 |
| 文章里图片排版错乱 | 图片尺寸差异过大 | 上传前统一宽度,或压缩时限制最大边长 |
这张表里有一个值得额外说明的点:换电脑导致配置丢失。PicGo 的图床配置、令牌都是存在本地的,很多人换台机器就懵了,不知道怎么配回来。解决办法是定期导出配置文件,或者在笔记里把仓库名、分支名、存储路径这些静态信息记下来,只有令牌需要重新生成。这个准备工作花两分钟,将来能省掉一次完整的排查。
另外一个常见问题是图片尺寸不一致导致排版难看。你从不同来源截的图,宽度可能是 800、1200、2560 像素混杂,放进同一篇文章里会出现明显的参差。最省事的做法是在压缩环节统一把最大边长限制到 1920,这样一来所有图片的显示宽度基本一致,排版自然就整齐了。前面给的 Actions 配置里那行-resize '1920x1920>'就是干这件事的,顺带还压了体积,一举两得。
6.3 最后再分享几个我一直在用的小技巧
第一个是上传前先重命名。我习惯把文件名改成"文章主题-序号"的格式,比如picgo-config-01.png。这样即使将来链接挂了,光看 URL 我大概能想起这是哪张图、在哪篇文章里用过,定位问题的速度快很多。
第二个是给图床仓库单独建一个 README。里面写清楚这个仓库的用途、目录结构规则、命名规范、令牌的更新周期。听起来有点小题大做,但这个 README 在我把仓库交接给同事、或者自己隔了半年再回来维护时,救过两次命。
第三个是把常用的上传命令做成别名。我在 shell 配置里加了一行,把那段批量上传脚本简化成一个短命令,写文档时直接imgup *.png就能传完整个目录,比打开图形界面拖拽快得多。工具链这东西,用得越顺手,你越愿意坚持用它,图床这种需要长期维护的东西尤其如此。
第四个是关于图片格式选择的取舍。截图、图表、带文字的图用 PNG,色彩丰富的照片用 JPEG,需要同时兼顾质量和体积的场景可以试 WebP。WebP 的兼容性现在基本没问题,主流浏览器都支持,压缩率比 JPEG 高不少。但要注意文件扩展名必须正确,否则 CDN 返回的内容类型会不对,浏览器可能直接下载而不是显示。