起因嘛,就是这条短信:
【七牛云服务】尊敬的七牛云CDN用户,您的账号 **@**.com 下 article-assets.lynan.cn 等 3 个域名绑定的证书即将过期,为保证您的服务正常使用,请您尽快更换证书。详见邮件内容。您可登录「消息设置/产品消息/CDN 相关通知」关闭短信通知。如证书已弃用请忽略。
收到七牛的短信说明我的免费证书一年期又到了,需要重新申请、上传 SSL 证书。正好我最近因为迁移了博客到 CloudFlare,体验不错,干脆把图床也迁移了。
总得来说,迁移的好处有:
- 表钱
(免费套餐包含 10GB 以内的资源,目前来说我肯定用不到限额,因为我的资源在上传前都手动压缩过,当然了如果真到不够用的时候它超出额度也非常便宜)
- 全球CDN
- 无需自行配置 SSL 证书
继续用七牛的话,一年配置一次我都有点懒😅
收集原图床资源
鉴于当时为我的博客单独建了一个 Bucket 并且配置了单独的域名,所以找起来很容易。跑个脚本即可:
我的博客是 Hexo 生成的,原始文件都在 source
文件夹内。
getlinks.js1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| const { resolve } = require("path"); const { readFileSync, writeFileSync, promises } = require("fs"); const { readdir } = promises;
const directory = "source";
async function getFiles(dir) { const dirents = await readdir(dir, { withFileTypes: true }); const files = await Promise.all( dirents.map((dirent) => { const res = resolve(dir, dirent.name); return dirent.isDirectory() ? getFiles(res) : res; }) ); return Array.prototype.concat(...files); }
const getLinks = () => { const res = {};
const checkContent = (files) => { files.forEach(filePath=>{ const fileContent = readFileSync(filePath, "utf8"); const matchRes = fileContent.match( /https:\/\/article-assets.lynan.cn[^"'()>\s]+/gi ); if (matchRes && matchRes.length) { matchRes.forEach(link => { let linkText = link; if (linkText.includes("?")) { linkText = linkText.split("?")[0]; } if (!res[linkText]) { res[linkText] = 1; } }) } }) };
getFiles(directory).then((filePath) => { const files = filePath.filter((item) => !item.endsWith(".DS_Store")); checkContent(files); const links = Object.keys(res).join("\n"); writeFileSync("qiniuLinks.txt", links); }); };
getLinks();
|
下载资源到本地
震惊了属于,七牛的 Web 端后台只能一个一个下载,批量下载其实是打开 n 个标签页,有点原始。
七牛有 SDK ,但是我作为一个切图脚本仔,还是再写一个脚本吧。。
这里的脚本的目的是为了保留原始文件的目录层级,这样的话当我上传完毕以后,只需将原来的资源 URL 更换为最新的域名即可。(或者直接把原来的 Bucket 的域名解析到新图床 Bucket)。
downloadfiles.js1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| const axios = require("axios"); const fs = require("fs"); const _ = require("lodash");
const files = fs.readFileSync("files.txt", "utf-8").split("\n"); const directory = "files";
const domain = "https://article-assets.lynan.cn/";
let errorFiles = ''
const downloadFile = async (filePath) => { try { let paths = _.compact(filePath.replace(domain, "").split("/")); paths.length = paths.length - 1; console.log(paths); if (!fs.existsSync(`${directory}/${paths.join("/")}`)) { fs.mkdirSync(`${directory}/${paths.join("/")}`, { recursive: true }); } const file = await axios.get(filePath, { responseType: "stream" }); file.data.pipe( fs.createWriteStream(`${directory}/${filePath.replace(domain, "")}`) ); } catch (error) { console.log(filePath); errorFiles += filePath return true; } };
const task = async () => { for (let i = 0; i <= files.length; i++) { await downloadFile(files[i]); } if(errorFiles){ fs.writeFileSync('errorFiles.txt', errorFiles) } };
task();
|
上传到 CloudFlare R2
没有 Bucket 的新建一个 Bucket 先。
把下载好的文件拖进去上传。
替换原链接域名
我直接用 VS Code 的“查找和替换” 换好了。
打开检查一下,OK,丝滑。迁移以后只要我的域名还在,我的博客和 CloudFlare 共存亡😄
为什么不用第三方图床
其实我用了,还付费了。主要还是怕不知道什么时候突然就跑路了,不如大公司靠谱。
有点觉得不靠谱是因为我用的那个图床,似乎也是迁移了好几次(现在访问原始链接会有多个 302 重定向,虽然不影响访问,但是变慢的体感是挺明显的),在使用期间我也遇到过几次间歇性不可用,所以稳定性这一块也是有点担忧的。
R2 缓存头设置
R2 添加自定义域名以后,默认的配置是:Cache-Control: public, max-age=0, must-revalidate
。
对于我来说,我的当前 R2 存储桶都是用于存储不会改变的文件(图片、视频等),如果需要改变我会重新上传使用新的 URL。
因此我希望将 max-age
修改到一个月的时间。
进入 CloudFlare 域名后台: /rules/transform-rules/modify-response-header
添加一个规则,为此存储桶的域名添加响应头:
1 2 3 4 5 6 7 8 9 10 11 12
| If... When incoming requests match…
Custom filter expression
When incoming requests match…
Hostname equals r2-assets.lynan.cn
Then...
Add Cache-Control = max-age=43200000
|
PS. 这篇文章本来没想写,不过想想从业几年,还是挺经常写脚本的,分享一下也很有意思。