最近把一个自己在用的 TXT -> PDF 在线工具整理开源了。
项目地址:
- 在线体验:txt2pdf.vercel.app/
- GitHub:github.com/xqnode/txt2…
(欢迎star🥰)
这个项目本来只是想解决一个很朴素的问题:
把中文 TXT 文件稳定地转成 PDF。
但真正做起来之后,问题很快就从“文本转 PDF”本身,变成了:
- 中文渲染怎么保证不乱码
- 大文件怎么处理
- Serverless 平台上怎么避免请求体超限
- 多片 PDF 最后怎么合并才不会炸
最后整理成了这个项目:
- 支持中文 TXT 转 PDF
- 支持大文件分片转换
- 支持浏览器端合并 PDF
- 支持部署到 Vercel
- 支持在线上传、预览、导出
为什么会做这个
很多在线 txt 转 pdf 工具在下面这些场景里很容易出问题:
- 中文内容导出后乱码
- 稍大一点的 TXT 文件直接失败
- 代码、日志、小说这类纯文本内容导出排版一般
- 放到 Vercel 这种 Serverless 平台后,大文件流程很容易撞限制
这个项目就是围绕这些问题一点点补出来的。
最初方案其实很直观
一开始的思路很简单:
- 前端上传 TXT
- 后端把文本转成 PDF
- 如果文件太大,就切片上传
- 后端再把多个 PDF 片段合并成一个完整 PDF
看起来很合理,但真正部署到 Vercel 之后,很快就遇到了问题。
真正的坑:不是转换,而是“合并”
单片转换其实问题不大。
文本按 3MB 左右切片后,逐片调用 /api/convert,每片独立生成 PDF,这一段在 Vercel 上是能跑通的。
真正麻烦的是最后一步:
多个 PDF 片段怎么合并。
最开始我走的是服务端合并:
- 每片 TXT 转完后得到 PDF
- 前端把这些 PDF 再传给
/api/merge - 后端用
pypdf合并
这个方案本地没问题,但在线上很快碰到典型错误:
FUNCTION_PAYLOAD_TOO_LARGE
Request Entity Too Large
也就是说:
问题不是 Python 逻辑写错,而是合并请求本身超过了平台限制。
为什么会超限
原因其实也不复杂。
大文件会被切成多个文本片段,每个片段再转换成 PDF。
如果最后把这些 PDF 一次性回传给服务端合并,不管你是:
- JSON + base64
- multipart/form-data
- 分批合并后再继续上传
只要合并后的中间 PDF 越来越大,最终还是会继续撞请求体上限。
这类问题在 Serverless 场景里特别典型:
- 单步逻辑看起来没问题
- 但链路一长,请求体、超时、内存这些限制就会一起冒出来
最后怎么解决
最后这条链路我改成了:
后端负责“生成每一片 PDF”,浏览器负责“合并所有 PDF”。
也就是:
text
TXT 大文件 → 前端切片 → 每片请求 /api/convert → 得到多个 PDF Blob → 浏览器端使用 pdf-lib 合并 → 直接下载最终 PDF
这一步改完之后,整个思路就顺了很多:
- Vercel 只负责单片 PDF 生成
- 不再承受超大的 merge 请求体
- 最容易炸的部分直接转移到浏览器端
- 大文件场景也更稳定
这其实是一个很典型的经验:
当平台对请求体和函数执行有明显限制时,尽量让服务端做“单步、短链路、可分片”的事,把可前移的聚合逻辑前移到客户端。
当前实现方案
项目现在的核心思路是:
1. 中文 PDF 渲染
使用 reportlab + STSong-Light CID 字体,解决中文显示问题。
2. 大文件分片转换
前端读取 TXT 后按字节分片,避免单次请求过大。
3. 浏览器端合并 PDF
前端拿到所有片段 PDF 后,通过 pdf-lib 在浏览器中直接合并,不再依赖服务端 merge。
4. Vercel 部署
保留“静态前端 + Python Function”的简单部署结构,尽量让项目易部署、易演示、易复用。
适合什么场景
这个项目目前比较适合:
- 中文小说 TXT 转 PDF
- 代码文件、日志文件归档成 PDF
- 做一个可在线使用的 txt2pdf 小工具
- 参考“Serverless + 浏览器端合并”的处理方式
目前仓库已经补了这些内容
为了把它做成一个更完整的开源项目,我也顺手把仓库门面整理了一下:
- 中英文 README
- 在线演示地址
- 首页截图
- Demo GIF
- Use Cases
- Roadmap
- v1.0.0 tag / release
仓库地址:
github.com/xqnode/txt2…
后续计划
后面还打算继续补这些能力:
- 自定义边距、字号、行距
- 页眉页脚、页码、封面
- 更多文本格式支持
- 更适合超大文件的后端方案(对象存储 / 队列 / 任务化处理)
最后
如果你也在做这类文本处理、PDF 导出,或者刚好在 Vercel / Serverless 场景里碰到类似的请求体限制问题,欢迎来看看这个项目。
在线体验:
txt2pdf.vercel.app/
GitHub:
github.com/xqnode/txt2…