视频教程#
前言和项目特点#
-
本文介绍用 GitLab 作为图库并用 GitHub 作为备份。
-
前面介绍了如何用 GitHub 作为图库并用 GitLab 作为备份,【GitHub 私库作图床,PicGO 上传,Cloudflare Workers 加速,Gitlab 实时备份】 ,此为反向操作。
-
针对新建博客中大量使用图片,故需搭建一个私人图床。既要避免使用收费的商业云 oss 储存;又要在白嫖的前提下找个长期稳定的存放平台;还要兼顾访问速度;最好有异地灾备。为了实现这些目标,便有了以下综合解决方案。
方案特点和优势:
- 存储在 GitLab 私库:图片存放在 GitLab 私有仓库中,路径经过脱敏处理,确保安全性;平台比 GitHub 还要稳。
- 自动压缩图片:通过自动压缩图片,提升加载速度,优化用户体验。
- Cloudflare CDN 加速:利用 Cloudflare CDN 提供的全球加速服务,确保图片快速加载。
- 自定义域名:支持使用自定义域名,提升品牌形象和专业性。
- 多种链接形式输出:生成多种形式的图片链接,方便在博客或其他平台使用。
- 实时备份到 GitHub 私库(可选): 将 GitLab 实时备份到 GitHub 私有库提供了数据冗余和跨平台备份,增强了数据安全性和保障了业务连续性。
条件#
- GitLab 账号,https://gitlab.com
- GitHub 账号,可选项,如不需要备份可忽略,https://github.com
- Cloudflare 账号,https://www.cloudflare.com
- Tinypng 账号,https://tinypng.com/developers
- 安装 Snipaste,https://zh.snipaste.com
- 安装 PicGo,https://molunerfinn.com/PicGo
流程和工具介绍#
截图:使用 Snipaste 进行截图,这一款简单但强大的贴图工具,支持截屏、标注等功能,适用于 Windows 和 Mac。
PicGo 上传图片到 GitHub:使用 PicGo ,并安装 picgo-plugin-compress-next 插件,自动压缩图片后上传到 GitHub。
获取经过 Worker 处理的图片链接:自动生成经过 Worker 隐藏 GitLab 私库的 API,增加 CDN 和双栈,输出自定义域名 url。
自动从 GitHub 推送最新图片到 GitLab:使用 GitLab CI/CD,一旦数据有更新,自动化备份到 GitHub,避免图片全部丢失的风险。
详细关键步骤#
前置条件,新建 GitLab 私库,获取 GitLab API 和项目 ID#
- 登陆 GitHub,访问 https://gitlab.com/projects/new#blank_project 新建项目,并建一个私库用于存放图片,现在 GitLab 每个项目为 4G 大小,超过就再建新的可以了
- 获取项目读写权限的 API
- 获取项目 ID
获取 Tinypng API Key#
- 注册 Tinypng.com 账号,访问 https://tinypng.com/developers 注册
PicGo 设置#
- 安装好 PicGo 后,继续在软件里安装 picgo-plugin-compress-next 插件(此步可能需要开启科学)
- 安装好 gitlab-file 插件(此步可能需要开启科学)
- 继续设置 PicGO 主程序
名称 | 介绍及配置示例 |
---|---|
图床配置名 | 起个自己便记的即可,默认 Default |
gitlab 服务器地址 | https://gitlab.com |
项目 id | 填写前面获取的 GitLab 项目 ID |
默认分支 | 填 main ,如填其他,后面的 worker 反代要作相应的改动 |
gitlab 的 token | 填写前面获取的 GitLab 项目 API (PicGo 会明文保存) |
文件名及其路径 | <图片存放的自定义路径>/{fileName} |
上传文件的 Message | Upload {fileName} By PicGo gitlab files uploader at {year}-{month}-{day} |
自定义链接格式 | !(https://<worker 自定义域名>/<GitLab 图库项目名>/<图片存放的自定义目录,可以多层>/$fileName$extName) |
Cloudflare 创建 worker#
- 登陆 Cloudflare,访问 https://dash.cloudflare.com/ ,新建 worker
- 部署后,编辑代码,复制并按图修改相应两处位置
// 定义 GitLab 仓库名称、仓库 ID 和 API 令牌
const REPO_CONFIG = [
{ name: 'repoName1', id: 'repoID1', token: 'repoAPI1' },
{ name: 'repoName2', id: 'repoID2', token: 'repoAPI2' },
{ name: 'repoName3', id: 'repoID3', token: 'repoAPI3' },
];
async function handleRequest(request) {
const url = new URL(request.url);
const pathParts = url.pathname.split('/').filter(Boolean);
console.log('URL:', url.toString());
console.log('Path parts:', pathParts);
if (pathParts.length < 1) {
return new Response('Invalid URL format', { status: 400 });
}
const gitlabRepo = pathParts[0];
console.log('Requested repo:', gitlabRepo);
const repoConfig = REPO_CONFIG.find(repo => repo.name === gitlabRepo);
if (!repoConfig) {
console.log('Repository not found in config. Available repos:', REPO_CONFIG.map(r => r.name));
return new Response('Repository not found', { status: 404 });
}
const { id: gitlabRepoId, token: gitlabApiToken } = repoConfig;
// 获取剩余路径并进行编码
const remainingPath = pathParts.slice(1).join('/');
const encodedPath = encodeURIComponent(remainingPath);
console.log('Remaining path:', remainingPath);
console.log('Encoded path:', encodedPath);
// 构建 GitLab API URL
const apiUrl = `https://gitlab.com/api/v4/projects/${gitlabRepoId}/repository/files/${encodedPath}/raw?ref=main`;
console.log('GitLab API URL:', apiUrl);
try {
// 发起请求到 GitLab API
const response = await fetch(apiUrl, {
method: 'GET',
headers: {
'PRIVATE-TOKEN': gitlabApiToken
}
});
console.log('GitLab API response status:', response.status);
if (!response.ok) {
return new Response(`Error fetching from GitLab: ${response.statusText}`, { status: response.status });
}
// 返回 GitLab 的响应
const contentType = response.headers.get('Content-Type');
const body = await response.arrayBuffer();
console.log('Content-Type:', contentType);
return new Response(body, {
status: response.status,
headers: {
'Content-Type': contentType,
'Cache-Control': 'public, max-age=3600' // 缓存一小时
}
});
} catch (error) {
console.error('Error:', error);
return new Response(`An error occurred: ${error.message}`, { status: 500 });
}
}
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request));
});
- 添加自定义域名,可以用 worker 给的域名
https://<workerName>.<cloudflareUser>.workers.dev
先试试
正式使用流程#
截图#
- 使用 Snipaste 进行截图到粘贴板,可以使用快捷键 (默认 Ctrl + F1)
上传图片#
- 通过 PicGo 上传图片到 GitHub,可以使用快捷键(默认 Ctrl + Shift + P)或拖拽图片到 PicGo 界面
- 上传成功进度条是蓝色的,如果是红色,请检查设置是否有误。上传成功后自定义域名链接会自动在粘贴板
- 在相应的场景 Blog 或者论坛等地址粘贴出来
实时备份到 GitHub (可选)#
Github 设置#
- 登陆 GitHub,创建备份项目库,访问 https://github.com/new
Gitlab 设置#
有两个方法,选其中一种即可:1. 使用 GitLab 平台的镜像功能(推荐); 2. 使用 CI/CD 工作流
方式 1:GitLab 平台的镜像功能#
方式 2:通过 CI/CD pipeline#
- 在 CI/CD 处创建三个环境变量
变量 | 说明 |
---|---|
GITHUB_USERNAME | GitHub 的用户名 |
GITHUB_REPO | 填写前面创建的 GitHub 备份库名字 |
GITHUB_PAT | 填写前面获取的 GitHub PAT Token |
- 创建备份到 GitHub 的 CI/CD Pipeline,代码如下:
image: alpine:latest
variables:
GIT_STRATEGY: clone
before_script:
- apk add --no-cache curl git
sync_to_github:
script:
- |
# 获取本地和GitHub远程仓库最新commit hash,并显示
LOCAL_COMMIT=$(git rev-parse HEAD)
REMOTE_COMMIT=$(curl -s -H "Authorization: token ${GITHUB_PAT}" "https://api.github.com/repos/${GITHUB_USERNAME}/${GITHUB_REPO}/commits/main" | awk -F '"' '/"sha":/{print $4; exit}')
echo "Local commit: $LOCAL_COMMIT"
echo "Remote commit: $REMOTE_COMMIT"
# 比较本地和远程commit,如有更新,则推送到GitHub
if [ "$LOCAL_COMMIT" != "$REMOTE_COMMIT" ]; then
echo "Pushing updates to GitHub..."
git config --global user.email "${GITHUB_USERNAME}@gitlab.com"
git config --global user.name "${GITHUB_USERNAME}"
git remote add github https://${GITHUB_PAT}@github.com/${GITHUB_USERNAME}/${GITHUB_REPO}.git
git push github HEAD:main --force
else
echo "No updates needed."
fi
rules:
- if: $CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "web"
图片案例#
https://pic.forvps.gq/pic2/images/202410081627933.png