
写了几百篇技术笔记的人大多经历过同一个瞬间某天打开自己三个月前写的文档发现正文里十几张截图全变成了裂图点开链接要么返回一个 404要么返回一张写着该图片已失效的占位图还有的干脆跳到一个满是弹窗的网页。那一刻你才意识到自己当初以为传上去就永远在那儿的图其实一直寄存在别人的房子里而房子是可以拆的。外链相册解决的正是这个问题——它把一张图片从一个文件变成一串地址而你真正需要关心的从来不是上传按钮在哪里而是这串地址背后的存储、权限、带宽和生命周期是怎么被安排的。下面我按自己的实际使用经验把外链相册这个概念从定义、形态、搭建、翻车点到长期维护完整拆一遍适合写笔记、做文档、维护个人站点、做小程序或公众号配图的各类使用者参考哪怕你完全没接触过这个概念看完也能自己跑通一条可用的链路。1. 把外链相册这四个字拆开看很多人对这个词的模糊感来自于把它当成了一个产品名字。它其实不是它是一类能力的组合描述。1.1 存储、直链、管理三个缺一不可的环节一个东西要被称为外链相册必须同时满足三件事。第一是存储图片有一个稳定的落点。这个落点可以是第三方公共服务提供的空间可以是你自己开通的对象存储桶也可以是一台你自己维护的服务器上的目录。存储层决定了容量、成本和数据归属。第二是直链这个落点能对外暴露一个公开可访问的 URL任何人拿到这个 URL在浏览器里打开就能直接看到图片本身而不是先看到一个网页、再点一次下载按钮。直链是外链相册区别于普通网盘的核心特征也是最容易被误解的地方——很多人以为能分享就等于有直链这两件事差得很远。第三是管理你能对这个图片集合做基本的组织操作比如按目录分类、批量上传、批量删除、查看用量、设置访问策略。纯粹的直链不需要管理但一旦图片数量上到几百张没有管理能力的存储就会变成一堆无法检索的散件。这三者里存储是最容易解决的花钱或者用免费服务都行管理是体验问题忍一忍也能过只有直链是硬门槛它决定了你这条路走不走得通。1.2 为什么普通网盘的分享链接不能直接拿来用我用一个生活化的类比来解释。假设你要给别人寄东西普通网盘的分享链接相当于给对方一个驿站地址取件码对方得先到驿站把取件码报给工作人员工作人员核对之后再把包裹从货架上拿下来交给他。整个过程中对方拿到的是一个包裹但中间隔了一道人工流程。而直链相当于把包裹直接放在对方家门口他推门就能拿到。这两种方式在结果上看起来差不多但在引用场景下的差别是灾难性的。你在 Markdown 文档里写下一行图片语法渲染器会直接拿这个 URL 去请求二进制内容它不会模拟点击、不会填验证码、不会等待页面跳转、更不会处理 JavaScript 渲染出来的下载按钮。如果你的链接指向的是一个 HTML 页面渲染器拿到的就是一段 HTML 文本图片位置自然是一片空白。同理博客附件库的问题不在于没有直链而在于链接被绑死在平台内。你在某个写作平台上传的图片它的地址里往往带着平台自己的路径结构一旦你把文章导出成 Markdown 搬到别处或者平台调整了资源路径规则所有图片引用会在一夜之间集体失效。这就是为什么很多人的文章迁移之后看起来像被洗劫过一样。一个简单的判断原则如果你的图片链接里出现了平台的域名路径、需要登录态才能访问、或者打开后地址栏发生跳转那它就不是可以长期依赖的外链。1.3 一分钟判定一条链接是不是真直链不用装任何工具用浏览器和一条命令就能验证。最快的方式是无痕窗口直接打开。开一个干净的无痕窗口粘贴链接回车。如果页面直接铺满一张图地址栏里的 URL 没变右键能看到图片另存为那基本就是直链。如果出现的是网页框架、有下载按钮、有推荐内容或者地址栏跳到了别的路径那就不是。更严谨的方式是看响应头里的内容类型。命令行里发一个只取头部的请求curl -I https://img.example.net/notes/2024/demo-01.webp真正可用的图片直链返回大概长这样HTTP/2 200 content-type: image/webp content-length: 87432 cache-control: public, max-age31536000而一个看起来能打开的伪直链往往是这种HTTP/2 200 content-type: text/html; charsetutf-8 content-length: 21430第二组里的content-type是text/html意味着你请求回来的是一个网页。这就是为什么有些链接你手动点开明明能看到图但放进文档里就是裂的——你看到的图是那个网页自己渲染出来的而文档要的是二进制。除了内容类型还有两个字段值得留意。content-length告诉你图片实际大小可以用来判断是不是被服务端替换成了一张占位图占位图通常只有一两千字节。cache-control决定了这张图在客户端和中间节点缓存多久缓存时间长的图片在重复访问时体验会好很多这一点在做公开站点时尤其重要。2. 把图片变成地址之后到底换来了什么理解了定义还得理解动机。如果只是传个图很多人会觉得用平台自带的附件功能就够了何必多折腾一层。这取决于你的使用强度。2.1 一次上传、多处引用写作链路上的复用红利我的实际情况是同一张架构图会同时出现在至少四个地方本地 Markdown 笔记、团队内部文档、一篇对外发布的文章、以及一份给同事的临时说明。如果每个地方都单独上传一份那这张图在我这里就有了四份副本任何一次修改都要改四处漏掉一处就会出现版本不一致。有了外链之后这张图只存在一个地方四个场景全部引用同一个 URL。改图的时候我只覆盖那一个文件所有引用位置自动同步——因为链接没变内容变了。这个特性在需要反复迭代的图示上价值极高尤其是那种每次评审都要微调的技术架构图。这里有个容易被忽略的细节覆盖更新时必须保持文件名不变。很多人习惯用带时间戳的文件名觉得这样不会冲突但代价是每次更新都要回头去改所有引用位置复用的红利直接就没了。正确的做法是文件名作为稳定标识内容可以变文件名不变确实需要保留历史版本的用目录区分比如同一张图在v1/和v2/下各放一份引用时按需切换。2.2 站点带宽与源站的解耦如果你维护着一个访问量还过得去的站点图片往往是最吃带宽的资源。一篇文章正文可能只有 30KB配图却有 800KB比例悬殊得离谱。把所有图片都放在站点源服务器上等于让一台小机器承担全部图片流量稍微有点访问量就会顶到带宽上限页面加载慢得像在上古时代。把这些图片挪到专门做静态资源分发的服务上源服务器只负责输出 HTML 和接口响应压力立刻就不一样了。更进一步静态资源服务通常自带边缘缓存能力同一张图被不同地区的访问者请求时可以直接从就近的缓存节点返回不必每次都回源。这套机制对个人站点来说几乎是免费的性能提升因为你不需要自己搭任何缓存层。真正的收益不只是快而是故障隔离。图片服务出问题时页面的文字内容仍然能正常展示只是图挂了源服务器出问题时已经缓存下来的图片仍然能正常访问。两个部分各自独立互不牵连。2.3 跨设备、跨工具的一致性这一点用过的人体会很深。我在台式机上整理好的笔记换到笔记本上打开图照样在用手机上的编辑器打开同一份文档图也在甚至把这份文档发给一个完全没装任何同步工具的人他打开也能看到完整的图。原因很简单——图片不在本地也不在某个需要同步的目录里它就在那个 URL 上。对比一下本地相对路径的方案所有图片放在./assets/目录下一旦你把单个 md 文件发给别人图全没了一旦目录结构变动路径全断。这种方案在单人单机场景下没问题但只要涉及分享和跨设备必然要付出代价。3. 四种常见形态以及各自的取舍外链相册不是只有一种做法。按控制权从低到高排大致是四档每一档都对应着不同的成本和风险结构。3.1 第三方公共服务上手最快控制权最低这类服务的特点是注册即用上传界面友好上传完直接给你一个链接复制走。适合的场景很明确临时用、少量用、对长期可用性没有强要求。它的代价也很明确。第一你无法控制它的存续。这类服务大多靠广告或者有限的捐赠维持运营方一旦停止投入你的图片会在没有任何提前通知的情况下消失。第二你无法控制它的策略。有些服务会在检测到大量外链请求后悄悄加上来源校验导致你的图在特定站点上突然全部 403。第三你无法控制它的内容审核尺度某些图片可能被判定为不合规而屏蔽而你连申诉渠道都找不到。我一般建议把这类服务定位成草稿期工具写文章时快速传图、拿到链接先排版等文章定稿准备长期发布时再把图迁移到更可控的地方。把它当长期仓库用早晚会付出代价。3.2 对象存储自己开户、自己配权限这是目前最主流也最均衡的方案。它的本质是一个通过 HTTP 接口访问的海量文件系统你创建一个桶把文件放进去配置好读权限就能拿到标准的直链。它的优势在于三件事。一是权限模型清晰你可以精确控制哪个桶是公开读、哪个是私有、私有桶的临时链接有效期多久。二是接口标准化上传、删除、列举都可以用脚本批量完成不需要依赖图形界面。三是计量透明用了多少存储、跑了多少流量后台都有明确数字成本可以预估。需要自己动手的地方在于桶的访问权限默认往往是私有的你得手动把它改成公共读才能对外提供直链这中间涉及到一个容易搞错的点——桶级别的公共读和对象级别的公共读是两回事。有些人只改了单个文件的权限结果新上传的图还是访问不了有些人把桶设成了公共读却忘了这会连带影响桶里所有文件包括那些本该保密的。这个坑后面会详细讲。另外对象存储的直链域名通常是服务商提供的默认域名这个域名在某些客户端环境里可能存在兼容问题比较稳妥的做法是绑定一个自己的域名并配上证书既好看也更好控制。3.3 自建服务把最后一块拼图拿回来自建的意思是在一台自己的服务器上跑一个图片管理程序或者干脆就是一个配置好静态文件服务的目录。这条路控制权最高数据在自己手里访问策略自己定容量只受磁盘限制也不会有人突然改规则。代价是运维成本。你要处理的事情包括服务器到期续费、系统更新、证书到期自动续签、磁盘容量监控、被恶意刷流量时的限流配置。这些事情平时不占时间但一旦出问题就是半夜被叫起来处理的那种。我的建议是如果你已经有了一台常年运行的服务器比如用来跑别的服务的机器顺手加一个图片目录的成本几乎为零那自建是划算的。如果为了外链相册专门去开一台机器那就是为了一个次要需求承担了一份主要运维负担不太值。3.4 四类方案的取舍对照把关键维度拉平了看会清楚很多维度第三方公共服务对象存储自建服务静态托管上手难度极低中等较高低数据归属平台平台你可导出完全自有平台你可导出长期存续可控性低中高高中成本结构免费或极低按量计费固定服务器成本免费额度内为零批量操作能力弱强有标准接口强中等适合场景临时、草稿长期主力有现成服务器轻量个人站选型的时候我通常按这个顺序问自己三个问题这些图我要用多久如果超过一年就把第三方公共服务排除掉。我需不需要用脚本批量处理如果需要就排除掉只能靠网页点击的方案。我有没有现成的服务器如果有自建可以作为兜底选项。4. 从零跑通一条可用外链的完整链路概念讲清楚了接下来是动手部分。这一节我按实际操作顺序走一遍包含那些文档里不会写但实际会卡住你的细节。4.1 上传前必须做的四件事文件名规范化。这是最容易被跳过、后期最痛苦的一步。规则很简单全小写、只用英文字母数字和短横线、不含空格、不含中文、不含特殊符号。原因有三中文文件名在不同系统间传递时会被百分号编码成一长串%E5%9B%BE...贴进某些编辑器里会被截断空格在 URL 里会变成%20某些渲染器处理不好特殊符号里的#会被识别成锚点?会被识别成查询参数起始符直接导致链接指向错误。推荐的结构是日期或主题 序号 简短描述比如2024-06-notes-01-arch-overview.webp。这个命名同时解决了排序、检索和唯一性三个问题。尺寸与格式压缩。手机截图动辄两三千像素宽、几兆大小直接传上去既浪费流量又拖慢加载。实际正文里显示的宽度一般不超过 800 像素做成 1600 像素宽已经足够应对高分屏文件体积能降一个数量级。格式上带透明通道的图用 PNG照片和截图优先用 WebP兼容性没问题而且体积通常只有 PNG 的三到五成。如果是纯图标类的小图也可以考虑矢量格式但注意矢量格式在部分渲染环境里支持不完整涉及跨平台引用时还是位图更稳。剥离元数据。这条单独拎出来讲因为它的后果不是不好看而是泄露信息。手机拍的照片默认带 EXIF里面可能包含精确的拍摄坐标、设备型号、拍摄时间。你把这些图传到公开可访问的地址上等于把这些信息也一起公开了。截图类图片相对安全但相册类、实拍类内容风险很高。用脚本处理是最省事的Pillow 几行代码就能搞定from PIL import Image def normalize(src, dst, max_width1600, quality82): with Image.open(src) as im: im im.convert(RGB) if im.width max_width: ratio max_width / im.width im im.resize( (max_width, int(im.height * ratio)), Image.LANCZOS ) # 不传 exif 参数默认就不会写入原始元数据 im.save(dst, WEBP, qualityquality, method6)这里的关键点是保存时不显式传入exif参数。很多人的代码是从别处抄来的里面带着exifim.info[exif]这种写法那条语句的作用恰恰是把原始元数据原样保留下来跟你的隐私目标完全相反。统一目录规划。上传之前先想清楚目录结构别等文件堆到几百个再来整理。我用的结构是按年月分层加用途分类notes/2024/06/、posts/2024/q2/、assets/icons/。分层的好处是列举和批量操作时范围可控删除旧内容不会误伤新内容。4.2 拿到链接的三种方式网页控制台上传。最直观适合零星几张图。上传后服务方一般会给出一个可复制的地址注意要选公开访问地址而不是临时签名地址后者带有效期过了时间就失效了很多人踩这个坑是因为两个按钮挨得太近点错了。命令行或脚本上传。批量场景必用。对象存储类服务一般都提供标准的 HTTP 上传接口脚本里发一个 PUT 请求从响应里解析出地址就行。下面是个简化示意# 仅示意请求结构实际签名逻辑按各服务文档实现 curl -X PUT \ -H Content-Type: image/webp \ -H Authorization: 按服务方规则生成的签名 \ --data-binary ./2024-06-notes-01-arch-overview.webp \ https://storage.example.net/my-bucket/notes/2024/06/2024-06-notes-01-arch-overview.webp这个方式的好处是可以在上传前就确定最终 URL不需要等服务方返回因为对象存储的路径就是你写入时指定的 key。这意味着你可以先把 Markdown 里的引用写好再跑脚本把本地图批量推上去一次对齐。桌面客户端配合快捷键。日常写作时最顺手的方式。配置好之后截图后按一个快捷键客户端会自动完成压缩、上传、把 Markdown 语法写进剪贴板你回到编辑器里直接粘贴就行。这条链路省掉的是打开网页、点上传、选文件、等进度、复制地址这五个动作写长文时能省下大量上下文切换成本。4.3 在文档里正确引用Markdown 的图片语法很简单方括号里是替代文字它不只是好看——图片加载失败时读者看到的就是这段文字屏幕阅读器也是靠它来描述图片内容的。写一句准确的描述比写图片两个字要有用得多。需要控制显示尺寸或者加懒加载时改用 HTML 标签img srchttps://img.example.net/notes/2024/06/2024-06-notes-01-arch-overview.webp alt架构总览 width720 loadinglazy /这里有两个实际会遇到的坑。一是必须写完整的绝对地址包括https://协议前缀。有些人生成的是//img.example.net/...这种省略协议的写法在浏览器里能正常工作但部分 Markdown 渲染器、邮件客户端、以及一些文档导出工具会把它当成相对路径结果是链接拼错、图片全裂。二是链接里带多个查询参数时要检查转义。有些服务的图片处理参数形如?x1y2在某些编辑器里会被转义成amp;导致参数被当成 URL 的一部分请求直接失败。还有一点值得说尽量别在链接里塞中文。虽然技术上经过编码是可以工作的但编码后的长串在某些环境下容易被截断而且完全无法阅读出问题的时候你根本看不出链接指向哪里。4.4 上线前的三项验证上传完、引用写完别急着发布做三个检查。第一换环境打开。在无痕窗口里、在手机上、在另一台设备上各打开一次。这一步能发现绝大多数来源校验类的问题——因为无痕窗口的 Referer 是空的如果链接在无痕下打不开说明服务端加了来源限制。第二确认内容类型。用前面提到的curl -I看响应头content-type必须是image/*。这一步能发现伪直链也就是那种手动点开能看到图、文档里加载不出来的情况。第三确认覆盖更新后链接不变。如果你的工作流涉及后期改图测试一次覆盖上传然后刷新引用页面看是否更新。有些服务的默认域名会带内容指纹文件一改 URL 就变这种特性对静态站点是好事对外链引用是灾难必须提前确认清楚。5. 那些让图片集体消失的原因以及怎么查外链相册真正让人头疼的不是怎么用而是明明昨天还好好的今天全挂了。这一节我把几种常见故障的成因和排查链路完整写一遍方便你遇到问题时按顺序走。5.1 403 的来源来源校验是怎么工作的图片能访问但被拒绝最常见的原因是服务端做了来源校验。原理不复杂浏览器在请求图片时会在请求头里带上一个Referer字段说明这个请求是从哪个页面发起的。服务端拿到这个字段和预设的白名单比对不在名单里就返回 403。这个机制原本是为了防止别人直接盗用你的图片资源、消耗你的流量但对正常使用外链的人来说它经常误伤。因为不同场景下Referer的表现差异很大从网页里点开是完整地址从 HTTPS 页面引用 HTTP 资源时浏览器出于安全策略可能完全不发送无痕窗口、隐私模式、某些客户端软件里Referer是空的。排查方法很清楚用命令行分别带和不带Referer头请求对比结果。# 不带来源 curl -I https://img.example.net/notes/2024/06/demo-01.webp # 带一个来源 curl -I -H Referer: https://my-site.example.org/article/1 \ https://img.example.net/notes/2024/06/demo-01.webp如果第二种返回 200、第一种返回 403那基本可以确认是来源校验。解决方式有两条要么在服务端把来源白名单配成允许空来源很多服务有允许空 Referer的开关要么把引用你图片的所有站点域名加进白名单。前一种做法更省事但会削弱防蹭流量的效果后一种更安全但每新增一个引用站点就要维护一次。我个人倾向后一种因为白名单数量多了之后误放行导致的流量损失也是实实在在的。5.2 图片消失的完整排查链路遇到图挂了别急着重传按下面这个顺序走一遍能定位到绝大多数问题。第一步确认单个链接的状态码。拿到具体地址curl -I看返回。404 表示文件不存在——可能是被删了、被迁移了、或者路径拼错。403 表示存在但拒绝访问——原因见上一节。301 或 302 表示发生了跳转——外链最怕这个因为很多渲染器不跟随跳转。200 但内容是text/html——说明这个地址指向的是网页而不是图片。第二步确认是不是全局性故障。如果所有图都挂那大概率是域名解析、证书过期或者服务方整体故障。这种情况下看单个文件没意义直接去看服务方的状态页或者自己的证书有效期。证书过期是个特别隐蔽的原因因为浏览器会给出一个警告页而文档渲染器则会直接静默失败。第三步确认是不是被限流或超额。如果是按量计费的服务账户欠费或者超出配额之后请求会被拒绝表现可能是 403 也可能是返回一张统一的占位图。这种情况下content-length往往只有几百到一两千字节和原图的体积差着量级很容易分辨。第四步确认引用本身有没有写错。这一步听起来很蠢但实际发生率极高。常见写法错误包括协议头缺失、域名拼错一个字母、路径里少了目录层级、链接尾部多了空格或者换行符。最后这个尤其阴险因为在编辑器里完全看不出来复制到别处才能发现。有个简单办法把链接单独粘到浏览器地址栏如果能打开说明链接本身没错问题在引用环境如果打不开问题就在链接本身。第五步确认是否是浏览器缓存导致的假象。有时候图片其实已经挂了但你本地因为缓存还在正常显示导致你看不出问题而别人打开就是裂的。排查时一定要用无痕窗口或者强制刷新。我把这套链路整理成一张对照表方便查的时候直接对号入座现象最可能的原因优先验证动作全部图片 404目录被整体删除或迁移检查服务端文件列表部分图片 404单文件被清理或路径写错逐条 curl 比对在站点上 403直接打开正常来源校验带和不带 Referer 对比请求手动能看文档里不显示伪直链返回 HTML查 content-type所有图都是同一张小图超额后被替换为占位图查 content-length 和账户用量时好时坏缓存或节点不一致多次请求对比响应头突然全部失败且无响应证书过期或域名解析异常查证书有效期5.3 被低估的风险元数据泄露与目录遍历外链相册的公开性是一把双刃剑。你为了让它能被任何人访问就得把读权限开放出去而一旦开放任何拿到地址的人都能访问包括那些你没打算给他看的东西。元数据泄露前面提过主要是照片的地理位置和设备信息。还有一个容易忽略的点文档类文件的属性里可能带作者名、编辑历史、原始路径。如果你的外链相册不只存图片还存了一些导出的文档这些属性会一并公开。目录遍历是更严重的一类。有些自建服务的默认配置允许列出目录内容也就是说别人只要把你某张图的地址砍掉最后一段就能看到一个完整的文件列表进而把你所有的图都翻一遍。如果你的目录命名又是有规律的那基本上等于全部公开。检查方法很简单拿一张图的地址把文件名部分删掉只保留到目录然后在浏览器里打开。如果返回的是一个可点击的文件列表那就说明目录遍历是开着的需要去配置里关掉。同时检查一下有没有不该公开的目录被放在了公开路径下比如存放原始素材、草稿、备份的文件夹。还有一类风险来自链接的可猜测性。如果你的文件名都是01.webp、02.webp这种顺序命名那别人可以轻松地把整个相册爬下来。对完全公开的配图来说这无所谓但对只想给特定的人看的内容就必须用足够随机的文件名或者改用带有效期的临时签名链接。这也是我前面说文件名要包含描述性内容的原因之一——既解决了检索问题也顺带提高了猜测成本虽然这不是安全措施但总比纯序号强。6. 让这套东西能撑三年的维护动作外链相册不是配好就完事的它需要一点点周期性维护否则两年后你会面对一个自己都不敢动的黑盒。6.1 命名规范要落到脚本里而不是靠自觉规范写在文档里没用人一定会忘。把它固化到脚本里才可靠。我的做法是写一个上传前的预处理脚本输入一个原始文件输出规范化之后的文件同时打印出最终的引用地址。文件名不合规的直接拒绝尺寸超标的自动压缩元数据无条件剥离图省事的结果就是半年后整理不动。import re import pathlib SAFE re.compile(r^[a-z0-9][a-z0-9\-]{2,60}\.(webp|png|jpg)$) def check_name(path: pathlib.Path) - bool: if not SAFE.match(path.name): print(f命名不合规跳过: {path.name}) return False return True这个检查很粗暴但它拦住的问题比它放过的多。真正需要处理的是那批中文名、带空格、带括号的文件它们在某个环节一定会出问题早发现早改。6.2 备份与迁移假设服务明天就没了设计外链方案时我会先问自己一个问题如果这个服务明天停止运营我多久能恢复答案取决于两件事原始文件有没有本地副本以及引用地址是不是集中管理。第一件事比较好办上传之前保持一份本地原始文件按同样的目录结构存放定期整体同步一次。这样即使服务没了文件还在重新上传一遍就能恢复。但第二件事才是真正麻烦的——就算文件都在如果 URL 变了你所有文档里的引用全都要改。所以有一个做法值得推荐在自己的域名下做一层跳转或反代。对外暴露的地址永远是你自己域名下的路径实际指向哪里由你在后台配置。这样换服务商的时候只需要改一次映射规则所有引用位置都不用动。这一层可以简单到一个重定向规则也可以是一层反向代理复杂度看你需要多少控制力。代价是多了一个需要维护的环节但换来的是迁移时的从容我认为非常值得。还有一点经验不要把所有图放在一个桶或者一个目录下。按年份或者按用途分开好处是万一某一块出了问题影响范围可控而且迁移的时候可以分批做不用一次性搬完几百张。6.3 成本到底怎么算才不失控按量计费的服务成本由两块构成存储费和流量费。存储费跟文件总量挂钩通常很便宜流量费跟访问次数和单张大小挂钩是真正容易失控的部分。算一笔粗账假设你有 500 张图平均每张 120KB总存储约 60MB。这个量级的存储在绝大多数服务上都是微不足道的。但如果某篇文章被大量访问单日请求 5 万次每次 120KB那就是 6GB 的流出流量。这个数字在大促、爆款文章、或者被爬虫盯上的时候很容易出现。控制成本的手段有三个。一是压缩单张体积这是最直接的把 300KB 压到 120KB流量直接降六成。二是设置缓存策略让cache-control的max-age尽可能长同一用户重复访问时不再回源这一条对个人站点效果明显。三是配好来源白名单和用量告警防止被别的站点当成免费图床大规模盗用同时在用量异常时能第一时间收到通知而不是等到账单出来才发现。另外提醒一句免费额度和免费服务是两回事。免费额度是商业服务提供的用量区间超出之后按量计费账单是真实的免费服务则可能随时调整规则或者直接停止。前者可控后者不可控。如果你的图要长期用优先选前者。7. 我踩过几次之后的取舍最开始我也用过那种点一下就上传、立刻给链接的免费服务图省事前半年一切正常。转折点是有一次整理旧文档发现两年前的文章里图片失效率超过七成原因五花八门——有的服务关了有的改了访问规则有的把长期未访问的图清理了。那次之后我才把全部图片迁到对象存储上绑了自己的域名加了预处理脚本改了一下午但之后再没为图片的事操过心。现在我个人的做法是分两档日常写草稿、做临时说明用最快的方式拿到链接就行反正内容本身也是临时的一旦内容准备长期保留立刻走完整流程压缩、规范命名、剥元数据、传到正式存储、走自己的域名。这个分界线帮我省下了大量不必要的工作量也避免了在重要内容上偷懒。最后分享一个小技巧关于怎么快速判断一份旧文档还能不能救把文档里的所有图片链接批量提取出来逐条发一个只取头部的请求把返回码不是 200 或者内容类型不是image/*的挑出来。这个动作写成一个几十行的脚本跑一遍比你一张一张点开快几十倍而且能一次性看清整批图片的健康状况决定是补传还是放弃。踩过几次坑之后你会发现外链相册这件事真正的门槛不在上传而在于你有没有从一开始就把这些图要活多久这个问题想清楚。