七牛在线管理图片预览 Chrome 插件:TaoToken 统一 Key 配置与 settings.json 骨架
1. 七牛图片管理为什么需要一个 Chrome 插件七牛云对象存储给个人用户的免费额度是 10G放博客配图、项目截图、素材图基本够用。但真正让人头疼的不是存储而是管理。上传图片有各种 VS Code 插件、命令行工具可以搞定可一旦图片多了想回头找某张图来用就只剩登录七牛后台这一条路。七牛后台的资源列表页做得比较克制默认只显示文件名想看图片长什么样必须点「详情」弹窗关掉之后又不知道刚才看的是哪一张列表里也没有高亮聚焦排序只支持名称没有时间维度。图片一多找图就变成了体力活。所以思路很直接写一个 Chrome 插件注入到七牛后台的资源列表页监听它自己的列表接口请求请求成功后拿到文件名拼出访问地址直接在文件名旁边插入一个img标签。这样列表页就变成了带缩略图的图库不用点详情也能一眼看到图。这个插件本身不复杂真正容易翻车的地方在配置七牛有 AccessKey / SecretKey插件里可能还要调别的服务Key 一多就散落在 manifest、background、content 各处改一次要翻好几个文件。这篇就围绕「七牛在线管理图片预览 Chrome 插件」这个场景把配置统一到一份settings.json骨架里并用 TaoToken 的统一 Key 来收敛多 Key 分散的问题最后给出可复制的配置和验证动作。适合谁看已经在用七牛存图、想自己动手做预览插件的开发者手上有多套 API Key、被配置管理搞烦的人以及想找一个能同时对接多家模型/服务、又不想每个都单独维护密钥的方案的工程师。2. TaoToken 前置把散落的 Key 收成一份在动手写插件之前先把 Key 的问题解决掉。传统做法是每个服务一套 Key七牛的 AK/SK 一套如果插件里还想接个模型做图片描述或 OCR又是另一套。时间一长settings.json、环境变量、代码里到处是密钥改一个忘一个。TaoToken 在这里扮演的是统一 Key 入口的角色。你可以在它的控制台里创建 API Key然后用同一个 Key 去访问它支持的模型对话、编码等能力不用为每个下游服务单独记一套凭证。对插件这种小工具来说好处是配置项从「N 套 Key」变成「1 个 Key 若干服务地址」。需要提前准备好的东西一个 TaoToken 账号登录后进控制台创建 API Key七牛账号拿到 AccessKey / SecretKey以及你的绑定域名拼图片地址要用本地能跑 Chrome 的开发者模式用来加载未打包插件。相关入口我放在这里按需取用官网https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentAPI 基址https://taotoken.net/api控制台建 Keyhttps://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewriteAPI Keys 管理https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite模型对话https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewriteCoding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite注意TaoToken 的 Key 只用于它自身提供的接口七牛的 AK/SK 仍然要单独填在配置里两者不要混用也不要把七牛密钥写进任何会提交到公开仓库的文件。3. 可复制的 settings.json 配置骨架插件目录结构建议这样组织配置和代码分离改 Key 只动一个文件qiniu-preview-plugin/ ├── manifest.json ├── settings.json ├── scripts/ │ ├── background.js │ └── content.js ├── html/ │ └── popup.html └── images/ └── icon-48x48.pngsettings.json是整个插件的配置中心把七牛信息和 TaoToken 信息都收进来{ qiniu: { accessKey: 你的七牛AccessKey, secretKey: 你的七牛SecretKey, bucket: 你的空间名, domain: https://hopefully-img.yuedun.wang, listApiPattern: https://portal.qiniu.com/api/kodov2/rsf/list*, thumbnailSuffix: ?imageMogr2/thumbnail/!20p/ }, taotoken: { baseUrl: https://taotoken.net/api, apiKey: 你的TaoToken API Key, model: 默认模型名 }, preview: { insertCount: 50, imgWidth: 100px, enableThumbnail: true } }几个字段说明一下避免填错字段作用注意点qiniu.domain拼图片完整地址的前缀必须带https://结尾不要带/qiniu.listApiPattern监听七牛列表接口的匹配串用*通配别写死具体 bucketqiniu.thumbnailSuffix七牛图片处理参数缩略图用!20p想清晰点改!50ptaotoken.baseUrlTaoToken 接口基址固定https://taotoken.net/apipreview.insertCount每次插入多少张缩略图太大影响渲染50 比较稳manifest.json里要声明权限和注入规则重点是webRequest和content_scripts的匹配地址{ manifest_version: 2, name: qiniu-preview, version: 0.0.1, description: 七牛在线管理图片预览插件, permissions: [ cookies, webRequest, *://*/* ], background: { scripts: [scripts/background.js] }, content_scripts: [ { js: [scripts/content.js], matches: [ https://portal.qiniu.com/kodo/bucket/resource?bucketName* ], run_at: document_start } ] }这里有个细节matches里的bucketName*是为了适配不同空间如果你只用一个空间也可以写死。run_at用document_start是为了尽早挂上监听避免错过接口请求。4. 插件内图片预览请求的验证动作配置填好、插件加载之后怎么确认它真的生效了分三步验证从接口到 DOM 逐层确认。第一步确认 background 能监听到七牛的列表接口。打开七牛后台的资源列表页按 F12 进控制台切到 Network 面板筛选rsf/list刷新页面应该能看到这个请求返回 200。同时在 Console 里应该打印出details对象说明webRequest.onCompleted监听生效了。// background.js chrome.webRequest.onCompleted.addListener( function (details) { console.log(qiniu list request:, details.url, details.statusCode); if (details.statusCode 200) { chrome.tabs.sendMessage(details.tabId, list-done, function (res) { console.log(bg content:, res); }); } }, { urls: [https://portal.qiniu.com/api/kodov2/rsf/list*] } );第二步确认 content 收到消息并插入了 img。切到 Elements 面板搜索img看文件名单元格后面有没有多出img src...。如果没插入先看 Console 有没有报错再检查选择器是否匹配当前页面结构。// content.js chrome.runtime.onMessage.addListener((message, sender, sendResponse) { if (message ! list-done) return; const cells document.querySelectorAll(.ant-table-tbody tr td:nth-child(2)); const list Array.from(cells).slice(-50); list.forEach((cell) { const nameEl cell.querySelector(.formatted_2iUZF); if (!nameEl) return; const fileName nameEl.textContent.trim(); const img document.createElement(img); img.src https://hopefully-img.yuedun.wang/${fileName}?imageMogr2/thumbnail/!20p/; img.style.width 100px; nameEl.after(img); }); sendResponse(inserted); });第三步确认缩略图能正常加载。如果 img 插进去了但显示裂图多半是域名或文件名拼接有问题。在 Console 里手动拼一个地址打开看看// 在七牛后台页面的 Console 里执行 const testName 你的某张图片文件名.png; const url https://hopefully-img.yuedun.wang/${testName}?imageMogr2/thumbnail/!20p/; console.log(url); // 复制到浏览器新标签打开能显示说明域名和参数都对三步都通过说明从接口监听到 DOM 插入再到图片加载整条链路是通的。这时候你再看七牛后台的列表页每张图旁边都有缩略图找图效率会明显不一样。5. 本篇常见错排查实际搭的时候报错基本集中在几个地方我按出现频率排一下。监听不到接口请求。最常见的原因是manifest.json里没加webRequest权限或者urls匹配串写错了。七牛的列表接口路径可能随版本变化建议先在 Network 面板里确认实际请求地址再回填到urls里。另外manifest_version: 2和 3 的webRequest用法不同v3 需要改成declarativeNetRequest或换用其他方式别混着写。content 收不到消息。检查chrome.tabs.sendMessage的tabId是不是当前标签页以及 content script 是否真的注入到了这个页面。如果matches里的地址和实际页面 URL 对不上脚本根本不会执行。可以在 content.js 第一行加console.log(content injected)确认。img 插入了但位置不对。七牛后台的 DOM 结构会变.formatted_2iUZF这类类名是构建产物升级后可能变。稳妥的做法是用更稳定的选择器比如按td:nth-child(2)定位到文件名列再在列内找文本节点。如果类名变了用nameEl.after(img)之前先判断nameEl是否存在。缩略图裂图。三个可能域名没带https://、文件名里有特殊字符没编码、七牛空间没绑定域名或域名被回收。用encodeURIComponent(fileName)处理一下文件名再拼地址。如果域名本身访问不了先去七牛后台确认绑定域名状态。TaoToken Key 报 401。检查settings.json里的apiKey有没有多余空格以及baseUrl是不是https://taotoken.net/api。如果是在插件里发请求注意 Chrome 扩展的跨域限制需要在manifest.json的permissions里加上对应域名或者通过 background 转发请求。提示调试插件时background 的日志在「扩展程序」页面的「检查视图」里看content 的日志在页面 Console 里看两个地方别搞混。6. 配置生效后的下一步配置跑通之后这个插件已经能解决「七牛后台看图难」的问题了。如果还想往下走有两个方向可以试。一是把预览能力做得更完整比如加个点击缩略图放大、按上传时间排序、搜索文件名过滤。这些都是在 content.js 里加逻辑配置骨架不用动。二是把 Key 管理继续收敛。现在settings.json里还有七牛的 AK/SK 和 TaoToken 的 Key 两套如果插件后续要接更多服务可以统一走 TaoToken 的 Key把七牛相关的调用也封装成一层。需要建 Key 或看接入方式的话从 API Keys 和接入文档进去就行API Keyshttps://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite如果你主要是在编码场景里用比如让模型帮你改这个插件的代码可以看看 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite最后提醒一句settings.json里是明文密钥别提交到公开仓库。本地开发用.gitignore排除掉或者改成从环境变量读取。插件本身不复杂把配置理顺了后面加功能就是顺手的事。