Flask 单文件网盘系统 · 从零到上线完整指南
小吾云匣是一个基于 Python Flask 的单文件网盘系统,专为个人开发者和小团队设计。全部功能集成在一个 server.py 文件中,无需数据库、无需复杂配置,上传即用。
server.py 搞定一切,systemd 崩溃自动重启| 组件 | 技术 |
|---|---|
| 后端 | Python 3.8+ / Flask / Jinja2 模板 |
| 前端 | 纯 HTML/CSS/JS,零外部依赖 |
| 存储 | 本地文件系统,无数据库 |
| 进程守护 | systemd |
| 可选依赖 | Pillow(图片缩略图加速) |
| 项目 | 最低要求 | 推荐配置 |
|---|---|---|
| 操作系统 | Ubuntu 18.04 / CentOS 7 / Debian 10 | Ubuntu 22.04 LTS |
| CPU | 1 核 | 2 核 |
| 内存 | 512 MB | 1 GB |
| 磁盘 | 按需(建议 20 GB 起) | 按需 |
| 网络 | 公网 IP + 端口 80 可用 | 域名 + DNS 解析 |
| 软件 | 版本要求 | 用途 |
|---|---|---|
| Python | 3.8 及以上 | 运行 Flask 服务 |
| pip | 跟随 Python 版本 | 安装依赖 |
| Flask | 3.0 及以上 | Web 框架 |
| Pillow | 9.0 及以上 (可选) | 图片缩略图 |
| systemd | 系统自带 | 进程守护 |
以下操作在服务器终端逐条执行。
ssh root@你的服务器IP
# Ubuntu / Debian
apt-get update && apt-get install -y python3 python3-pip
# CentOS
# yum install -y python3 python3-pip
pip3 install --break-system-packages flask pillow
--break-system-packages 参数,否则会报错。如果不需要缩略图功能,可省略 pillow。
mkdir -p /opt/filebox/files
将 server.py 上传到服务器 /opt/filebox/ 目录。
# 方式一:scp 上传(在本地执行)
scp server.py root@你的服务器IP:/opt/filebox/
# 方式二:直接在服务器上用 cat 写入
# (复制 server.py 全部内容,粘贴到终端)
cd /opt/filebox
nohup python3 server.py > server.log 2>&1 &
浏览器打开 http://你的服务器IP,应看到登录页面。
1,建议首次登录后立即修改。文件存储在 /opt/filebox/files/,请确保磁盘空间充足。登录后,点击右上角「改密」按钮,输入旧密码和新密码即可。密码以 SHA256 哈希存储在 /opt/filebox/password.hash。
/opt/filebox/password.hash 文件,重启服务后会重置为初始密码 1。rm /opt/filebox/password.hash
systemctl restart filebox
所有文件存储在 /opt/filebox/files/。如需更换位置,修改 server.py 中第 10 行的 STORAGE 变量:
STORAGE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "files")
默认 7 天。修改 server.py 第 8 行:
app.config["PERMANENT_SESSION_LIFETIME"] = timedelta(days=7)
3 次失败触发数学验证码,5 次失败 IP 锁定 10 分钟。锁定时间和阈值可在 server.py 中调整:
# 第 68 行:锁定 600 秒(10 分钟)
_ip_attempts[ip][2] = now + 600
# 第 53 行:触发验证码的失败次数
if fail_count >= 3:
推荐使用 systemd 管理服务,支持开机自启、崩溃自动重启。
cat > /etc/systemd/system/filebox.service << 'EOF'
[Unit]
Description=小吾云匣 FileBox Service
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/filebox
ExecStart=/usr/bin/python3 /opt/filebox/server.py
Restart=always
RestartSec=5
StandardOutput=append:/opt/filebox/server.log
StandardError=append:/opt/filebox/server.log
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable filebox
systemctl start filebox
systemctl status filebox # 查看状态
systemctl restart filebox # 重启
systemctl stop filebox # 停止
journalctl -u filebox -f # 实时日志
tail -f /opt/filebox/server.log # 查看日志
如果需要 HTTPS 或与其他站点共用 80/443 端口,可使用 Nginx 反向代理。
apt-get install -y nginx
将 server.py 末尾的端口从 80 改为其他端口(如 5000):
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000, debug=False)
cat > /etc/nginx/sites-available/filebox << 'EOF'
server {
listen 80;
server_name 你的域名或IP;
client_max_body_size 2000m;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
EOF
ln -s /etc/nginx/sites-available/filebox /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx
client_max_body_size 控制 Nginx 层面的最大上传体积。Flask 本身无上传大小限制。修改后记得 nginx -s reload。如果服务器启用了防火墙,需要放行端口。
# ufw (Ubuntu)
ufw allow 80/tcp
ufw reload
# firewalld (CentOS)
firewall-cmd --add-port=80/tcp --permanent
firewall-cmd --reload
# iptables
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
云服务商(阿里云、腾讯云等)还需要在安全组中放行对应端口。
1 登录# 定期备份文件目录
tar -czf filebox-backup-$(date +%Y%m%d).tar.gz /opt/filebox/files/ /opt/filebox/password.hash
服务主页顶部显示已用 / 总磁盘空间,定期关注避免写满。
df -h /opt/filebox/files
server.py 覆盖 /opt/filebox/server.pysystemctl restart filebox| 方法 | 路径 | 说明 | 认证 |
|---|---|---|---|
| GET | / | 首页(文件列表 + 登录) | 否 |
| POST | /login | 登录 | 否 |
| GET | /logout | 退出登录 | 是 |
| POST | /upload | 上传文件(multipart) | 是 |
| GET | /download/<path> | 下载文件 | 是 |
| GET | /preview/<path> | 获取预览信息(JSON) | 是 |
| GET | /raw/<path> | 直接返回文件内容 | 是 |
| GET | /thumb/<path> | 图片缩略图(64px) | 是 |
| DELETE | /api/delete?path= | 删除文件/文件夹 | 是 |
| POST | /api/rename | 重命名文件 | 是 |
| POST | /api/share | 生成分享链接 | 是 |
| GET | /s/<token> | 分享链接下载 | 否 |
| GET | /api/zip?path= | 打包下载文件夹 | 是 |
| POST | /api/change-password | 修改密码 | 是 |
| POST | /api/exists | 检测文件是否存在 | 是 |
POST /api/share
Content-Type: application/json
{
"file": "文件名",
"dir": "子目录路径(可选)",
"hours": 6 // 有效时长:1/6/24/48/72
}
// 返回
{
"ok": true,
"link": "/s/xxxxxxxx",
"expires_in": "6小时"
}
POST /api/rename
Content-Type: application/json
{
"old": "旧文件名",
"new": "新文件名(需保留原后缀)",
"dir": "子目录路径(可选)"
}