个人网站图片从阿里云 OSS 迁移到 Cloudflare R2

个人网站这两个月访问量增加了不少,导致阿里云对象存储(OSS)费用涨幅很大,1 月 0.09 元、4 月 2.64 元,5 月直接 6.55 元。当初选择阿里云 OSS,就是因为便宜,现在它的这一特性逐渐丧失了。我个人网站部署在 GitHub Pages 上,使用 Cloudflare 做了缓存。因为网站本身就使用了 Cloudflare,加上 Cloudflare R2 的免费额度还能覆盖到目前我的使用量。所以将图片迁移到 Cloudflare R2。

Cloudflare R2 免费额度与国内访问效果

免费额度
存储 10 GB / month
A 类操作 每月 100 万个请求
B 类操作 每月 1000 万个请求
出口(数据传输到互联网) 免费

Cloudflare R2 国内网络访问速度(使用了 Argo Smart Routing):

阿里云 OSS 国内网络访问效果:

Cloudflare 的访问速度平均只比阿里云的访问速度慢一倍,还可以接受。

设置 Cloudflare R2 存储桶可公网访问

设置自定义域,如:hexoblog.r2.depp.wang

设置后可通过: https://hexoblog.r2.depp.wang/cookie-copy.mp4 公网访问 hexoblog 桶中 cookie-copy.mp4

阿里云 OSS 数据下载

下载配置命令行工具 ossutil 后,使用命令下载所有数据:

ossutil cp -r oss://deppwang/blog/ /Volumes/NAS/Documents/阿里云对象存储/deppwang/blog-20240618

数据上传到 Cloudflare R2

Cloudflare R2 使用 AWS S3 存储,macOS 安装 awscli:

brew install awscli

Cloudflare R2 中创建 API 令牌,复制「访问密钥 ID (Access Key ID)」、「机密访问密钥 (Secret Access Key)」,使用 aws configure 命令配置,配置后数据在文件 ~/.aws/credentials 中。

配置 endpoint_url

vim ~/.aws/config
[default]
region = auto
output = json
endpoint_url = https://xxx.r2.cloudflarestorage.com

上传

# 上传单个文件
aws s3 cp /Volumes/NAS/Documents/阿里云对象存储/deppwang/blog-20240618/cookie-copy.mp4 s3://hexoblog/cookie-copy.mp4

# 上传文件夹
aws s3 cp /Volumes/NAS/Documents/阿里云对象存储/deppwang/blog-20240618/ s3://hexoblog/ --recursive

替换指定文件夹中所有文档中的图片链接

使用脚本实现,以下是我替换我 Obsidian 文件夹的 Python 脚本(ChatGPT 生成)

import os
import re

# 定义旧的和新的图床链接
old_link = "https://deppwang.oss-cn-beijing.aliyuncs.com/blog/"
new_link = "https://hexoblog.r2.depp.wang/"

# Obsidian 文件夹路径
obsidian_folder = "/Users/depp/Documents/Obsidian"

# 正则表达式模式
pattern1 = re.compile(r'!\[\]\(' + re.escape(old_link) + r'([^\)]+)\)')
pattern2 = re.compile(r'!\[([^\]]*)\]\(' + re.escape(old_link) + r'([^\)]+)\)')
pattern3 = re.compile(r'<img src="' + re.escape(old_link) + r'([^"]+)"')

def replace_links(file_path):
with open(file_path, 'r', encoding='utf-8') as file:
content = file.read()

# 替换链接
content = pattern1.sub(r'![](' + new_link + r'\1)', content)
content = pattern2.sub(r'![\1](' + new_link + r'\2)', content)
content = pattern3.sub(r'<img src="' + new_link + r'\1"', content)

with open(file_path, 'w', encoding='utf-8') as file:
file.write(content)

def traverse_folder(folder_path):
x = 1
for root, _, files in os.walk(folder_path):
for file in files:
# if x > 100:
# return
if file.endswith(".md"): # 假设 Obsidian 笔记文件是以 .md 结尾
file_path = os.path.join(root, file)
replace_links(file_path)
print(f"Processed: {file_path}")
x += 1


# 开始遍历文件夹并替换链接
traverse_folder(obsidian_folder)

如果使用 PicGo 图片上传,搜索 s3 插件安装。

我个人网站文章使用 Obsidian 存放,当我替换 Obsidian 文档的图片链接后,个人网站文章的图片也就会自动同步替换了。

如果你遇到图片打不开,或者加载比较慢,请给我留言反馈一下,感谢。

deppwang wechat

评论默认使用 ,你也可以切换到 来留言。