CloudGallery:零成本打造无限容量的 iOS 风私有图床
摘要:受够了第三方图床的限制?担心数据安全?本文介绍如何利用 Python Flask 和 Hugging Face Spaces,零成本搭建一个支持无限存储、私有加密、且拥有 iOS 磨砂质感 UI 的个人图床系统。
1. 背景与痛点
作为一名技术爱好者,在撰写博客或使用 Obsidian/Notion 做笔记时,图床是不可或缺的基础设施。但市面上的解决方案总是不够完美:
第三方图床:存在收费、容量限制或跑路风险。
GitHub 仓库:国内访问不稳定,且存在仓库大小限制。
对象存储 (OSS/S3):按流量计费,一旦被恶意刷流量,费用不可控。
服务器搭建才是最优解,但没有服务器怎么办呢?
于是我将目光投向了 Hugging Face (HF)。HF 提供的 Dataset 存储不仅免费、理论容量无限,而且由大厂背书,稳定性极高。基于此,我开发了 CloudGallery —— 一个高颜值、私有化的图床解决方案。
2. 界面设计:追求极致的“果味”
在设计 UI 时,我抛弃了传统的后台管理风格,深度参考了 iOS 的设计语言,采用了大量的 毛玻璃(Glassmorphism) 特效。
2.1 极简登录
登入界面为了保证私有性,图床自带鉴权系统。登录页采用动态壁纸加磨砂玻璃卡片,清爽无广告。
2.2 沉浸式管理
主界面主界面支持批量多选上传,后端会自动将文件名处理为短字符(如 a9b2.jpg),避免文件名冗长。
2.3 悬浮预览 (Lightbox)
点击图片后,不再是生硬的页面跳转。我实现了一个悬浮预览层,背景自动进行高斯模糊(Blur)处理,图片悬浮于主页之上。底部配有类似 iPhone 相册的 Filmstrip(胶卷栏),支持丝滑的左右滑动切换。
预览页3. 核心功能与技术实现
除了 UI,CloudGallery 在功能上也解决了几个核心痛点。
3.1 核心痛点:GitHub 401 问题
这是开发过程中遇到的最大技术挑战。
如果将 HF Dataset 设为 Private(私有),GitHub 无法直接访问图片链接(报错 401 Unauthorized)。
如果设为 Public(公开),则所有人都能看到你的所有图片,隐私无法保障。
3.2 解决方案:反向代理模式 (Proxy Mode)
我在 Flask 后端实现了一个中转接口。当你复制链接时,得到的是我的应用地址;当 GitHub 请求图片时,我的服务器会拿着私有 Token 去 HF 取回数据,再流式转发给 GitHub。
核心代码片段 (main.py):
import requests from flask import Response @app.route('/file/') def get_image_file(filename): # 1. 构造真实的 HF 原始地址 url = f"https://huggingface.co/datasets/{DATASET_NAME}/resolve/main/{filename}" # 2. 带着服务器端的 Token 进行鉴权请求 headers = {"Authorization": f"Bearer {HF_TOKEN}"} # 3. 使用 stream=True 进行流式转发,降低内存占用 r = requests.get(url, headers=headers, stream=True) return Response(r.iter_content(chunk_size=1024), content_type=r.headers.get('Content-Type'))
3.3 其他特性
无限存储:基于 Hugging Face Datasets。
隐私安全:Dataset 设置为 Private,只有通过你的 App 鉴权后才能上传/删除。
极简文件名:使用 UUID 前4位生成短文件名。
文件名生成逻辑
name = f"{uuid.uuid4().hex[:4]}{ext}"
4. 部署教程:如何拥有同款?
本项目基于 Docker 部署,你可以直接在 Hugging Face Spaces 上免费托管。
准备工作
一个 Hugging Face 账号。
项目开源地址:GitHub - CloudGallery (欢迎 Star)
第一步:创建存储仓库
登录 Hugging Face,点击 New Dataset。
起个名字(例如 my-images)。
关键点:Type 选择 Private(私有)。
第二步:获取 Access Token
进入 Settings -> Access Tokens。
创建一个新 Token,权限必须选择 Write(写入权限)。
复制这个 Token (hf_xxxx...)。
第三步:创建应用容器 (Space)
点击 New Space。
SDK 选择 Docker。
Hardware 选择默认的 Free 即可。
第四步:配置环境变量
在 Space 的 Settings -> Variables and secrets 页面,添加以下变量:
变量名 描述 示例值 HF_TOKEN 刚才复制的 Write Token hf_... DATASET_NAME 你的数据集名称 username/my-images ADMIN_USER 自定义登录账号 admin ADMIN_PASS 自定义登录密码 password123
第五步:上传代码
将项目中的 main.py 和 Dockerfile 上传到 Space 的 Files 中。等待几分钟构建完成后,点击 App 即可开始使用!
⚡ 进阶:国内访问加速 (Cloudflare Worker)
由于 Hugging Face 官方域名 (hf.space) 在国内访问不稳定或被阻断,推荐使用 Cloudflare Worker 进行反向代理。
⚠️ 注意: 为了支持反向代理和自定义域名,请务必使用本项目中的 cf.py 文件。
1. 部署代码选择
本项目提供了两个版本的核心代码:
main.py (标准版):适合海外环境,逻辑纯净,默认生成官方直链。
cf.py (国内加速版):国内用户请用这个! 它增加了 CUSTOM_DOMAIN 支持,修复了反代环境下的登录跳转和链接生成问题。
食用方法: 在将代码上传到 Hugging Face Space 时,请 直接复制 cf.py 的内容覆盖到 main.py(或者修改 Dockerfile 的启动命令为 CMD ["python", "cf.py"])。
2. 创建 Cloudflare Worker
登录 Cloudflare,进入左侧 Workers & Pages。
点击 Create Application -> Create Worker -> Deploy。
点击 Edit code,清空原有代码,粘贴以下内容:
export default { async fetch(request, env, ctx) { const url = new URL(request.url); // ⚠️ 修改这里:填入你 Space 的真实直连地址 (不要带 https://) const targetHost = "你的用户名-项目名.hf.space"; url.hostname = targetHost; url.protocol = "https:"; // 构造请求 const newRequest = new Request(url.toString(), { method: request.method, headers: request.headers, body: request.body, }); return fetch(newRequest); }, };
点击右上角 Deploy 保存。你将获得一个 xxx.workers.dev 的访问地址。
(可选推荐):在 Worker 的 Settings -> Triggers 中绑定你自己的自定义域名 (如 img.yourdomain.com),访问更稳定。
3. 配置 Space 适配反代域名
回到 Hugging Face Space 的 Settings -> Variables and secrets,新增一个变量:
类型 变量名 描述 示例值 Variable CUSTOM_DOMAIN 你的 Worker 地址或绑定的自定义域名 (必须带 https,不带结尾斜杠) https://img.yourdomain.com
作用:cf.py 读取到此变量后,会自动修正登录跳转路径,并将主页生成的“复制链接”替换为你的加速域名,确保国内可访问。
5. 结语
CloudGallery 是一个典型的“小而美”的项目。它利用了开源社区的免费资源,通过 Python 简单的逻辑胶水,解决了一个实际的生产力痛点。
如果你也受够了商业图床的限制,不妨动手试一试,搭建一个完全属于自己的云端相册。
项目 GitHub 地址:
作者声明本文无利益相关,欢迎值友理性交流,和谐讨论~
