bepasty 局域网版:手机友好的文件 / 文字分享,支持续传与浏览器端加密
bepasty 是一个老牌开源“文件版 pastebin”:上传任意文件或一段文字,得到一个短链接,别人打开就能预览、下载。我们在它的基础上做了一个面向家庭 / 小团队局域网的派生版,源码公开:
两者都沿用上游的 BSD-2-Clause 许可证。

解决什么问题
家里几台电脑、手机之间传东西,常见做法是发微信、AirDrop 或者网盘。它们各有毛病:微信压缩图片、有大小限制;AirDrop 只在苹果设备之间;网盘要登录、要走外网。
我想要的是:局域网里开一个网页,手机上点一下就能传、传完自动复制链接;大文件传到一半断了能接着传;中文文件名不乱码;偶尔有私密文件,能加个口令再分享。上游 bepasty 的存储、权限和预览框架很扎实,但界面是英文桌面风格,浏览器上传不能续传,中文文件名会被过滤掉。于是在它上面改。
适合:家里或办公室有一台常开的机器、想要一个自己掌控的“传文件 / 贴文字”小站的人。不适合直接暴露到公网(见文末“安全与限制”)。
哪些是上游的,哪些是我们改的
上游 bepasty 由 Thomas Waldmann 等人自 2014 年起维护(本派生基于 2026-07-29 的上游 master)。下面这些是上游原有的:文件系统存储(.meta + .data)、过期时间、权限模型(read/create/modify/delete/list/admin)、Pygments 代码高亮、图片 / 音视频 / PDF / asciinema 预览、多文件合集、REST API、命令行清理工具。
服务端我们加了 20 个提交(约 7300 行增、1000 行删),分几类:
界面
- 重写成中文、移动优先的单页工作区:“上传”和“列表”在同一页切换,切到列表时正在进行的上传不会中断;没有 JavaScript 时仍退回普通表单,可用。
- 任何地方粘贴截图 / 文件即上传,
Ctrl/Cmd+Enter提交文字;单个上传完成后自动复制链接(浏览器拒绝时静默跳过)。 - 列表里就地重命名、删除、复制链接;
.txt显示前三行预览,链接可点击。 - 详情页:下载 / 复制内容 / 打开原文件 / 二维码,下面是“预览 / 文件信息 / 管理文件”三个标签;深色模式、大触控区域、iPhone 安全区适配。
- 复制链接在 iOS + http 下 Clipboard API 不可用时,退回为全选链接文本。

传输
- 浏览器分块上传支持暂停 / 继续 / 重试:服务端记录已提交的偏移量,只接受下一个连续块,缺口、重放、重叠一律 409;断线后客户端先问服务端已收到多少再续传。并发写入用每个文件一把锁(Linux 用 fcntl,Windows 用 msvcrt)。
- 存储读写块从 16 KiB 改为 256 KiB;下载时如果数据比记录的大小短,直接报错,不再悄悄发一个截断的文件。
- 去掉默认 5 GB 单文件上限(可配置),拒绝负数大小。
文件名与预览
- 保留中文等 Unicode 文件名(仍过滤控制字符和路径分隔符);下载头按 RFC 6266 同时给 ASCII 后备名和 UTF-8
filename*;REST 上传的Content-Filename头按 UTF-8 解码。 - Markdown / HTML 文件提供“渲染 / 纯文本”切换;渲染结果放在不允许脚本的沙箱 iframe 里,并且不发 Referer。

可选功能(默认关闭或可关)
- 浏览器端口令加密:勾选“加密”后,文件 / 文字在浏览器里用 AES-256-GCM 加密(PBKDF2-SHA-256 60 万次派生密钥),服务器只存密文,看不到口令、原文件名和类型。新格式按 512 KiB 分记录加密、逐块认证,所以加密大文件也能续传,下载时可以用 Service Worker 边解密边保存,不必整个读进内存。
- 自动标题(
AUTO_TITLES,默认关):没起名字的文字分享,后台调用本机 Ollama 模型起一个简短中文标题。 - 免密码模式(
PASSWORDLESS,默认开):信任网络里不用登录;关掉后恢复上游的口令权限,并保留可选的登录界面。 TRUSTED_SCHEME_PROXY_IPS:只信任指定网关 IP 发来的X-Forwarded-Proto,让 HTTPS 反代后面生成的链接是 https;Host 和客户端 IP 永远不取自请求头。
命令行客户端(2 个提交):分块上传复用同一个 HTTP 连接(keep-alive);管道输入用 1 字节预读判断最后一块,正好是 1 MiB 整数倍的输入也能正确结束;上传失败返回非零退出码;兼容新旧 python-magic,以及没有 pwd 模块的平台;中文等非 ASCII 文件名按 UTF-8 发送。它不支持浏览器端加密和续传,走的是普通 REST 上传。
架构
- 服务端:Flask 应用,任何 WSGI 服务器都能跑(开发用自带的
bepasty-server,生产建议 gunicorn);数据就是存储目录下每个文件一对.meta/.data。 - 浏览器上传:
/+upload/new建条目 → 按Content-Range逐块 POST →GET /+upload/<name>查询已收字节数用于续传。 - 加密:完全在浏览器内用 Web Crypto 完成;服务器存一个
application/x-bepasty-encrypted的不透明条目。打开时浏览器取密文、本地认证并解密;密文接口不需要口令,但从不返回明文,原有的读权限 / 过期检查照旧。格式规范写在仓库的docs/source/encryption.rst。
安装和使用
服务端(需要 Python ≥ 3.11):
git clone https://github.com/erniu96/bepasty-server
python3 -m venv venv && venv/bin/pip install ./bepasty-server
cat > bepasty.conf <<'EOF'
STORAGE_FILESYSTEM_DIRECTORY = '/srv/bepasty/storage'
EOF
BEPASTY_CONFIG=$PWD/bepasty.conf venv/bin/bepasty-server --host 0.0.0.0 --port 5000
# 生产:BEPASTY_CONFIG=... gunicorn --bind 0.0.0.0:5000 bepasty.wsgi
然后用手机或电脑浏览器打开 http://<这台机器的 IP>:5000/。要用加密功能,需要在前面放一个 HTTPS 反代(Web Crypto 只在 HTTPS 或 localhost 下可用)。
命令行客户端:
git clone https://github.com/erniu96/bepasty-client-cli
cd bepasty-client-cli && python3 -m venv venv && venv/bin/pip install -r requirements.txt
PYTHON=venv/bin/python bash command.txt -u http://<服务器>:5000 report.pdf
tar c logs | PYTHON=venv/bin/python bash command.txt -u http://<服务器>:5000 -n logs.tar -L 1d
-L 设保留时长(30min、2d、1w、f 永久),-p 传口令(关闭免密码模式时)。客户端每块读 1 MiB、Base64 后请求体约 1.33 MiB,反代的请求体上限要放到 2 MiB 左右。
怎么验证过
- 服务端 Python 测试 200 项通过(7 项跳过:1 项缺 python-magic,6 项是需要单独测试实例的 Selenium 测试),Node 前端测试(上传器、加密格式、流式解密 worker)通过(含无 JS 表单测试);仓库另有 Selenium 浏览器测试,这次没有跑。
- 命令行客户端 13 项测试通过,包括用本地 HTTP/1.1 服务器确认多块上传共用一个 TCP 连接、1 MiB 边界、空输入和中文文件名。
- 写这篇文章时,我在一个空的测试实例上用命令行客户端从管道上传 3 MB 随机数据,下载回来 SHA-256 一致;也上传过名为
体检报告 2026.bin的 3 MB 文件,服务器记录的文件名正确,下载回来 SHA-256 一致。本文截图都来自这个测试实例和示例文件。
这些测试覆盖的是协议和逻辑;加密大文件的 Service Worker 保存路径、iPhone Safari 上的原生保存,还没有在真机上逐一验收,不同浏览器的行为可能不同。
安全与已知限制
- 默认配置只适合可信局域网。
PASSWORDLESS = True意味着能访问服务的人都能看、改、删所有文件(包括锁定的),开发服务器默认监听所有 IPv4 网卡,也没有单文件大小上限。要放到不可信网络,请设PASSWORDLESS = False、强SECRET_KEY、明确的PERMISSIONS、存储和请求大小限制,并加网络层防护。 - 加密保护内容,不保护可用性:其他有权限的人仍可删掉密文。忘记口令无法找回;密文可下载,所以口令要长、唯一,并和链接分开发送。被篡改的前端 JS、浏览器扩展或已被控制的设备不在保护范围内。
- 文件大小、保留时长和创建时间对服务器是可见的;加密文件显示为
加密分享.bepenc。 - 加密大文件下载需要 HTTPS + Service Worker + 可读流;不满足时会明确报错,不会退回到整文件读进内存。中途损坏会中断下载,已认证的前面部分可能留在半截文件里,要确认浏览器显示下载完成。
- 旧版(v1)加密格式只读兼容,单文件上限 128 MiB,需要整体解密。
- 命令行客户端:REST 协议无法表示空上传,空输入会报错退出。新版客户端按 UTF-8 发送文件名,连接旧版或上游服务端时中文名不能正确保存(不影响内容),服务端也要更新到当前版本。
- 这是个人维护的派生版,没有回合到上游,上游的在线文档不描述这些改动;派生版专属文档在仓库
docs/source/下。