☰
PicX 图床技术详解:基于 GitHub API 的图片上传托管与链接生成实现
2026/10/15 2:17:15 网站建设 项目流程
  • 开发工具
  • 前端

【免费下载链接】picx

🏞️ 一款基于 GitHub API 开发的图床工具,提供图片上传托管和生成图片链接。

项目地址:https://gitcode.com/gh_mirrors/pi/picx
点击查看免费下载

PicX 是一款完全基于 GitHub API 开发的开源图床工具,面向需要"图片上传托管 + 生成图片链接"的开发者和博客作者,提供在线使用、无需安装的 Web 服务形态。读完本文,你将掌握 PicX 的核心使用流程(OAuth 授权 / Token 登录、图床配置、多级目录管理)、上传与链接生成的工作原理(GitHub Git Database API 调用链、链接规则模板替换),以及图片压缩、水印、GitHub Pages 部署、PWA 离线化等进阶能力的底层实现。


一、PicX 是什么

PicX 的定位在 README.md 中一句话概括:一款基于 GitHub API 开发的图床工具,提供图片上传托管和生成图片链接。它不依赖任何自建后端服务,而是直接以浏览器为客户端,通过 GitHub REST API 把图片写入用户自己的 GitHub 仓库,再利用 GitHub、GitHub Pages、jsDelivr 等公开资源域名生成可访问的图片链接。

核心亮点

  • 在线使用、无需下载、无需安装:项目本身是一个纯前端应用(Vue 3 + Vite),部署在静态托管平台即可使用;
  • 操作简单、文档完善、持续维护:提供官方文档、快速开始教程与完善的设置项;
  • 代码开源、数据安全、完全免费:源码以 AGPL-3.0 协议开源(见 LICENSE),图片数据存放在用户自己的 GitHub 仓库中,不经过第三方中转服务器。

从仓库 package.json 可以看到,项目使用 pnpm 管理依赖(packageManager: pnpm@11.18.0),核心依赖包括vue@3.5、vue-router、pinia(状态管理)、element-plus(UI 组件库)、axios(HTTP 客户端)以及@jsquash/*系列浏览器端图片编解码库,运行环境要求 Node.js>=24 <25。

二、登录方式:GitHub OAuth 授权与 Token 填写

PicX 提供两种登录方式:

  1. GitHub OAuth 授权登录:通过 GitHub App 授权,换取可用于调用 API 的访问令牌;
  2. 填写 GitHub Token 登录:用户手动粘贴自己创建的 Personal Access Token(PAT),跳过 OAuth 流程。

无论哪种方式,最终都要得到一个有效 token 才能调用 GitHub API。底层实现上,所有请求都由 src/utils/request/axios.ts 中创建的 axios 实例统一发出:请求拦截器从本地存储读取用户配置(getLocal(LS_CONFIG)),当命中 GitHub API baseURL 且存在 token 时,自动向请求头注入Authorization: Bearer <token>。相关基础地址与超时配置在 src/common/constant/request.ts:AXIOS_BASE_URL = 'https://api.github.com',AXIOS_TIMEOUT = 300000(5 分钟,考虑到大图上传耗时)。

OAuth 授权状态(token、installationId、授权时间等)由 Vuex 模块 src/stores/modules/github-authorize/index.ts 管理并持久化到 LocalStorage。同时,src/common/constant/settings.ts 定义了GITHUB_AUTHORIZE_EXPIRE = 5 * 24 * 60 * 60 * 1000,即 GitHub App 授权 Token 的有效期为5 天,过期后需要重新授权。

登录后调用getGitHubUserInfo(见 src/common/api/user.ts)获取用户信息,用于展示头像、用户名,并作为图床仓库的 owner。

三、图床配置:仓库、分支与多级目录

登录后需要完成图床配置,核心配置项在 src/common/model/user-config.ts 的UserConfigInfoModel中定义:

配置项说明
owner/repo图床仓库的属主与仓库名
branch图片写入的目标分支(默认值为master,见 src/common/constant/init.ts 的INIT_REPO_BARNCH)
email/name提交 commit 时使用的 committer 信息
dirMode目录模式:rootDir(根目录)/dateDir(日期目录)/repoDir(仓库目录)/newDir(新建目录)
dirList仓库内的目录列表(供级联选择)

仓库的创建与初始化

  • 若还没有图床仓库,PicX 可调用createRepo(src/common/api/repo.ts)直接创建公开仓库,默认仓库名为picx-images-hosting(INIT_REPO_NAME,见 src/common/constant/init.ts);
  • 由于GitHub Git Database API 不支持在完全空的仓库上操作,initRepoREADME会先向仓库写入一个README.md文件完成仓库初始化(提交信息为Init repo via PicX),这是源码注释中明确说明的工程细节。

多级目录管理

getDirInfoList与getRepoPathContent(src/common/api/dir.ts)通过 Contents API(GET /repos/{owner}/{repo}/contents/{path},带ref=branch参数)拉取指定路径下的目录与图片,前端以级联组件(repo-dir-cascader)呈现多级目录。限制方面,src/common/constant/settings.ts 定义了NEW_DIR_COUNT_MAX = 5,即新建目录最多支持 5 级层级。

管理页的"上传时间"并非存储字段,而是通过getLatestCommitTime查询该文件路径最近一次 commit 的 author 时间获得(GET /repos/{owner}/{repo}/commits?path=...&per_page=1),这也是图床管理页能按时间排序的底层依据。

四、图片上传:四种选择方式与两条 API 链路

PicX 支持拖拽、复制粘贴、选择文件三种方式选择图片(README 中列为已实现功能),文件进入上传队列后统一走后续处理。

文件类型与大小限制

src/utils/file-utils.ts 中的isImage判定 png / jpg / jpeg / gif / webp / awebp / avif / svg / ico 等格式,isVideo仅支持MP4;IMG_UPLOAD_MAX_SIZE = 30(MB)与VIDEO_UPLOAD_MAX_SIZE = 30(MB)是上传大小上限(src/common/constant/settings.ts)。gettingFilesHandle负责把File通过FileReader转成 base64,并校验类型与大小。

上传前处理:压缩与水印优先

UploadImageModel(src/common/model/image.ts)同时保存originalBase64、watermarkBase64、compressBase64三份数据。真正上传时,src/utils/upload-utils.ts 按压缩结果 → 水印结果 → 原始数据的优先级取 base64 内容:

const tempBase64 = ( img.base64.compressBase64 || img.base64.watermarkBase64 || img.base64.originalBase64 ).split(',')[1]

即开启了压缩就传压缩后的图;否则开了水印就传带水印的图;两者都没开则传原图。

单张上传链路

单张上传使用 Contents API(src/common/api/upload.ts 的uploadSingleImage):

PUT /repos/{owner}/{repo}/contents/{dir}/{filename}

请求体包含message(Upload image via PicX)、branch、base64 形式的content;若配置了email,还会附加committer: { name: owner, email },使提交以用户身份记录(src/utils/upload-utils.ts 的uploadImageToGitHub)。

批量上传链路(Git Database API)

批量上传采用更高效的Git Database API 四步法(uploadImagesToGitHub):

  1. 创建 blob:getFileBlob把每张图的 base64 提交为POST /repos/{owner}/{repo}/git/blobs,返回 blob sha;
  2. 获取 head:getBranchInfo读取分支信息,得到根目录 tree sha 与 head commit sha;
  3. 创建 tree:createTree基于base_tree构建新 tree(mode100644、typeblob),见 src/common/api/merge.ts;
  4. 创建 commit 并移动 ref:createCommit以parents: [head.commit.sha]生成新 commit,createRef通过PATCH /repos/{owner}/{repo}/git/refs/heads/{branch}把分支指针指向新 commit,完成一次原子化的批量提交。

同样的 tree/commit/ref 组合也被批量删除复用:删除时将条目的sha置为null即表示从base_tree中删除对应路径(见 src/utils/image-utils.ts 的deleteImagesFromGitHub与 src/common/api/git-tree.ts 的注释)。单张删除则直接走 Contents API 的DELETE(src/common/api/delete.ts),需携带文件 sha。

文件名处理:重命名 / 哈希化 / 添加前缀 / 时间戳

src/views/upload-image/upload-image.util.ts 的generateUploadImageObject集中处理命名:

  • 重命名:名称中的空格统一替换为-;
  • 哈希化:默认开启(enableHash: true),以图片对象的 uuid 作为 hash 拼入文件名,格式为名称.uuid.后缀,确保重名图片在仓库内唯一;
  • 添加前缀:可配置固定前缀prefix,格式为前缀名称.uuid.后缀;
  • 时间戳命名:可开启enableTimestamp,名称整体替换为毫秒时间戳;该选项与哈希化、前缀互斥——在设置页切换时会自动关闭其他两项(见 src/views/picx-settings/picx-settings.vue 的onTimestampNamingChange);同一毫秒内批量添加时通过lastTimestamp + 1递增保证批内唯一。

五、图片链接生成:内置规则、自定义规则与格式转换

这是 PicX 的核心价值点:上传完成即生成可直接使用的图片链接,且支持多 CDN 规则自由切换。

链接规则模板

ImageLinkRuleModel(src/common/model/image.ts)将规则抽象为带占位符的 URL 模板。生成时(src/utils/image-link-utils.ts 的generateImageLink)用实际值替换四个占位符:

占位符替换值
{{owner}}仓库属主
{{repo}}仓库名
{{branch}}分支名
{{path}}图片在仓库内的完整路径

内置 5 种预设规则(初始值见 src/stores/modules/user-settings/index.ts):

// GitHub Pages https://{{owner}}.github.io/{{repo}}/{{path}} // GitHub 原始文件 https://github.com/{{owner}}/{{repo}}/raw/{{branch}}/{{path}} // jsDelivr CDN https://cdn.jsdelivr.net/gh/{{owner}}/{{repo}}@{{branch}}/{{path}} // Statically CDN https://cdn.statically.io/gh/{{owner}}/{{repo}}@{{branch}}/{{path}} // 国内 jsDelivr 镜像 https://jsd.cdn.zzko.cn/gh/{{owner}}/{{repo}}@{{branch}}/{{path}}

自定义配置链接规则:设置页提供ADD_IMAGE_LINK_TYPE_RULE/UPDATE_IMAGE_LINK_TYPE_RULE/DEL_IMAGE_LINK_TYPE_RULE三个动作(src/stores/modules/user-settings/index.ts),支持新增、编辑、删除规则,编辑时经imgLinkRuleVerification校验规则合法性(如必须包含必要占位符),满足任意自建域名或 CDN 前缀的场景。

链接格式转换

上传后支持一键复制链接,并可在Markdown / HTML / BBCode三种格式间自由转换(imageLinkFormat,默认关闭、选中 Markdown):

// Markdown imageName // HTML <img src="imageLink" alt="imageName" /> // BBCode [img]imageLink[/img]

transformImageLink(src/utils/image-link-utils.ts)在复制前按所选格式替换imageLink(生成的链接)与imageName(图片文件名去后缀)。批量复制(batchCopyImageLinks)则把多张图的链接按行拼接后一次性写入剪贴板,对应 README 中的"批量复制多张图片链接"。

六、图片压缩与图片水印

图片压缩(浏览器端编码)

PicX 内置高效压缩算法,可配置上传前自动压缩。压缩在浏览器端完成,不经过任何服务器:

  • 编码器枚举CompressEncoderEnum(src/common/model/image.ts)提供mozJPEG / avif / webP / png四种;默认开启压缩且编码器为webP;
  • 实现上基于@jsquash/*系列 WebAssembly 编解码库,由 src/services/image-codec.ts 的encodeImage创建独立 Web Worker(src/workers/image-codec.worker.ts)执行编码,任务结束即worker.terminate()释放资源,避免长时间占用主线程;
  • 仅对png / jpg / jpeg / webp / avif生效(isNeedCompress,见 src/utils/file-utils.ts)。

图片水印

src/utils/add-watermark.ts 使用 Canvas 2D 绘制水印,配置项与默认值如下(默认值见 src/stores/modules/user-settings/index.ts):

配置项说明默认值
text水印文字PicX
fontSize字号50
position位置:leftTop/leftBottom/rightTop/rightBottom/fullScreenrightBottom
textColor文字颜色(十六进制)#FFFFFF
opacity透明度0.5
rotate全屏水印旋转角度(度)-20
gap全屏水印平铺间距(px)80

单角水印通过strokeText + fillText绘制带描边的文字;fullScreen全屏模式下则以旋转矩阵在画布上按gap平铺,形成满幅斜纹水印。水印同样只对png / jpg / jpeg / webp / avif生效。

七、一键部署 GitHub Pages 与自定义域名

README 将 GitHub Pages 列为内置链接规则之一,与之配套的是一键部署能力。部署链路在 src/components/deploy-status-bar/deploy-status-bar.util.ts 的deployGhPages与 src/common/api/branch.ts 的checkoutGhPagesBranch中实现:

  1. 同步 CNAME:先把设置里的自定义域名同步到图床仓库当前分支根目录的CNAME文件(src/common/api/deploy.ts 的syncCloudCnameFile),包含规范化(去协议、去路径、小写)与格式校验(isValidCustomDomain);同步失败则中断部署;
  2. 检查 gh-pages 分支:存在则先删除,再从当前分支复制创建(POST /repos/{owner}/{repo}/git/refs,ref: refs/heads/gh-pages);
  3. 等待部署生效:由于 GitHub Pages 部署需要时间,源码以setTimeout(..., 50000)(约 50 秒)模拟部署进程,成功后自动把图片链接规则切换为GitHub Pages,并把部署状态写入仓库根目录的.deploy文件(saveCloudDeployInfo)。

自定义域名与.settings中的customDomain保持一致,保证部署结果与设置一致;域名置空时会清理仓库中的 CNAME 文件。

八、设置云端同步、PWA 与暗夜模式

设置云端同步

用户设置(UserSettingsModel,见 src/common/model/user-settings.ts)不仅保存在浏览器 LocalStorage,还可同步到图床仓库根目录的.settings文件(src/common/api/settings.ts)。由于水印文字等可能包含中文,源码特意实现了UTF-8 安全的 Base64 编解码(TextEncoder/TextDecoder配合btoa/atob),避免window.btoa对非 Latin1 字符抛异常;文件不存在则创建(Init settings via PicX),存在则带 sha 更新(Update settings via PicX)。

本地存储统一使用PICX_IH_前缀(src/common/constant/storage.ts):LocalStorage 保存CONFIG(用户配置)、SETTINGS(用户设置)、MANAGEMENT(管理页状态)、AUTHORIZATION(授权信息),SessionStorage 保存GLOBAL_SETTINGS(全局设置)。

PWA 支持

PWA 由 src/plugins/vite/pwa.ts 配置(vite-plugin-pwa,registerType: 'autoUpdate'),manifest 使用 public/logo@192x192.png 与 public/logo@512x512.png 作为应用图标。Workbox 除预缓存静态资源外,还做了两类运行时缓存:

  • 图片 CDN 缓存:对 GitHub raw / GitHub Pages / jsDelivr / Statically / 国内 jsDelivr 域下的图片资源采用StaleWhileRevalidate策略(缓存名picx-image-hosting-runtime,最多 500 条、保留 30 天),实现离线秒开;由于<img>请求为 no-cors 的 opaque 响应,cacheableResponse.statuses显式放行[0, 200];
  • 编解码器 wasm 缓存:CacheFirst缓存图片编解码用的.wasm文件,加速压缩模块加载。

配套的 src/utils/image-cache-utils.ts 提供purgeImageRuntimeCache:在覆盖上传、删除、移动、重命名成功后按仓库路径后缀清理缓存条目,避免管理页展示已被替换或删除的旧图(清理失败不影响主流程)。

暗夜模式与 i18n

  • 暗夜模式:ThemeModeEnum(src/common/model/user-settings.ts)支持system(跟随系统)/light/dark三种模式,默认system,由 src/utils/set-theme-mode.ts 应用到全局;
  • i18n:支持中文简体、中文繁体、英文三种语言(语言包见 src/locales/zh-CN.json、src/locales/zh-TW.json、src/locales/en.json),全局设置中可切换。

九、本地开发、构建与测试

仓库 package.json 提供完整的前端工程脚本:

# 安装依赖(pnpm 11.18.0) pnpm install # 本地开发 pnpm dev # 类型检查(vue-tsc + tsc) pnpm typecheck # 单元测试(Vitest) pnpm test # E2E 测试(Playwright) pnpm test:e2e # 代码规范(ESLint + Stylelint) pnpm lint pnpm lint:style # 生产构建 pnpm build # 一键全量校验:lint + style + typecheck + test + build pnpm verify

单测覆盖了目录图片列表 store(tests/unit/dir-image-list-store.test.ts)与文件工具函数(tests/unit/file-utils.test.ts),E2E 冒烟测试见 tests/e2e/smoke.spec.ts。

十、小结

PicX 用纯前端 + GitHub API 的组合,实现了一条完整自洽的图床链路:OAuth/Token 登录 → 仓库与多级目录配置 → 拖拽/粘贴/选择图片 → 压缩与水印处理 → Git Database API 批量提交 → 模板化生成链接 → 多格式复制 → 管理页批量删除与部署 GitHub Pages。其"数据存进用户自己的仓库、链接走公开 CDN"的架构,既保证了数据主权,又无需自建存储与流量服务,是理解"以公开平台 API 构建个人工具"这一工程范式的高质量参考实现。

如果想要深入代码,推荐从 src/utils/upload-utils.ts(上传核心流程)、src/utils/image-link-utils.ts(链接生成)、src/stores/modules/user-settings/index.ts(全部设置默认值)三个文件读起。

  • 开发工具
  • 前端

【免费下载链接】picx

🏞️ 一款基于 GitHub API 开发的图床工具,提供图片上传托管和生成图片链接。

项目地址:https://gitcode.com/gh_mirrors/pi/picx
点击查看免费下载

相关推荐

上一篇:深入理解Qwen2.5-7B-Instruct的AWQ量化策略:UINT4权重优化
下一篇:前端错误监控终极指南:Sentry在AI应用中的异常跟踪实践

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询