一、项目概述

Paperless-ngx 是一个文档管理系统,旨在将你的物理文档转换为可搜索的在线归档,让你真正做到"少纸化"(Paperless)。作为原 Paperless 和 Paperless-ng 项目的官方继任者,paperless-ngx 由社区团队共同维护,提供了更强大的功能和更活跃的社区支持。

核心特性:

  • 自动化文档处理:通过 OCR(光学字符识别)自动提取文档文本内容
  • 智能搜索:基于 Tantivy 的全文搜索引擎,支持复杂的查询语法
  • 文档分类与标签:支持自定义标签、文档类型和 Correspondent(发件人)管理
  • 多格式支持:支持 PDF、图片(JPG、PNG、TIFF 等)、Office 文档等多种格式
  • REST API:完整的 RESTful API,方便与其他系统集成
  • 现代化前端:基于 Angular 构建的响应式 Web 界面
  • Docker 部署:提供官方 Docker 镜像,支持一键部署
  • 多语言支持:通过 Crowdin 协调,支持多种语言翻译

适用场景:

  • 个人文档数字化归档(发票、合同、证件等)
  • 家庭文档管理(保险单、医疗记录、税务文件)
  • 小型办公室文档管理系统
  • 需要自托管解决方案的隐私敏感用户

二、技术原理

2.1 架构设计

Paperless-ngx 采用经典的前后端分离架构:

┌─────────────────────────────────────────┐
│           前端 (Angular)                 │
│  - 文档上传、浏览、搜索、管理界面        │
│  - 基于 TypeScript + Angular 17+        │
└─────────────────┬───────────────────────┘
                  │ REST API
┌─────────────────▼───────────────────────┐
│         后端 (Django + DRF)              │
│  - 文档处理流水线                        │
│  - OCR 识别与文本提取                    │
│  - 全文搜索 (Tantivy)                    │
│  - 用户认证与权限管理                    │
└─────────────────┬───────────────────────┘
                  │
┌─────────────────▼───────────────────────┐
│         任务队列 (Celery)                │
│  - 异步文档处理任务                      │
│  - 定时任务(文档消费、邮件检查等)       │
│  - 使用 Redis 作为消息代理               │
└─────────────────┬───────────────────────┘
                  │
┌─────────────────▼───────────────────────┐
│       存储层 (PostgreSQL/MySQL/SQLite)   │
│  - 元数据、标签、分类等信息              │
│  - 文档原始文件存储 (media 目录)         │
└─────────────────────────────────────────┘

2.2 核心技术栈与选型理由

后端技术栈:

  • Python 3.11+:现代化的 Python 版本,性能提升显著
  • Django 5.2+:成熟的 Web 框架,提供 ORM、认证、管理后台等基础设施
  • Django REST Framework:构建 RESTful API 的标准选择
  • Celery:处理异步任务(文档处理、邮件检查等),支持分布式部署
  • Redis:作为 Celery 的消息代理和结果后端,同时用于缓存
  • PostgreSQL/MySQL:生产环境推荐使用,支持完整的文本搜索特性

前端技术栈:

  • Angular 17+:企业级前端框架,TypeScript 原生支持
  • Angular Material:UI 组件库,提供一致的视觉体验
  • NgRx(可选):状态管理,适用于复杂的交互逻辑

文档处理技术:

  • OCRmyPDF:基于 Tesseract 的 OCR 引擎,支持多语言识别
  • PyMuPDF (fitz):高性能的 PDF 处理库
  • pdf2image:将 PDF 转换为图像,用于预览和 OCR 预处理
  • Tantivy:用 Rust 编写的全文搜索引擎库,性能优异

为什么选择这些技术?

  1. Django + DRF:快速开发,生态成熟,自带管理后台
  2. Celery:解耦耗时任务,提升用户体验
  3. Tantivy:比 Elasticsearch 更轻量,比 SQLite FTS 性能更好
  4. Docker:简化部署,确保环境一致性

2.3 关键算法与设计模式

文档处理流水线:

# 简化的文档处理流程(基于源码逻辑)
class DocumentProcessor:
    def process_document(self, document_id):
        # 1. 消费文件(从 consume 目录或上传)
        file_path = self.consume_file(document_id)
        
        # 2. OCR 识别与文本提取
        text = self.extract_text(file_path)
        
        # 3. 生成缩略图
        self.generate_thumbnail(file_path)
        
        # 4. 自动匹配规则(Correspondent、类型、标签)
        self.apply_matching_rules(document_id, text)
        
        # 5. 创建搜索索引
        self.update_search_index(document_id, text)
        
        # 6. 保存元数据到数据库
        self.save_metadata(document_id)

全文搜索实现:

Paperless-ngx 使用 Tantivy 作为搜索引擎,核心代码在 src/documents/search.py:

# 创建搜索索引
def add_or_update_document(document):
    writer = get_search_writer()
    writer.add_document(
        id=str(document.id),
        title=document.title,
        content=document.content,
        # 存储用于过滤的字段
        correspondent=document.correspondent.name if document.correspondent else "",
        tags=" ".join(tag.name for tag in document.tags.all()),
    )
    writer.commit()

异步任务设计:

使用 Celery 处理耗时操作,避免阻塞 Web 请求:

@app.task
def consume_file_task(file_path, override_filename=None):
    """消费上传的文件并创建文档"""
    # 文件消费逻辑
    document = consume_file(file_path, override_filename)
    
    # 触发异步处理
    if document:
        consume_file_task.apply_async(args=[document.id], countdown=5)

2.4 数据流分析

文档上传与处理流程:

  1. 用户通过 Web 界面或 API 上传文档(支持拖拽、多选)
  2. 后端接收文件,保存到 consume 目录(或直接处理)
  3. Celery 任务被触发,开始处理文档:
    • 检测文件类型(PDF、图片、Office 文档)
    • 如果是 PDF,检查是否已有文本层(避免重复 OCR)
    • 调用 OCRmyPDF 进行 OCR 识别
    • 提取元数据(创建时间、作者等)
    • 生成缩略图(小、中、大三种尺寸)
  4. 文档元数据保存到数据库
  5. 文档内容被索引到 Tantivy
  6. 用户可以在界面上搜索和浏览文档

搜索流程:

  1. 用户在搜索框输入查询(支持高级语法,如 tag:invoice date:2024-01)
  2. 后端解析查询,转换为 Tantivy 查询语句
  3. Tantivy 执行搜索,返回匹配的文档 ID
  4. 后端从数据库加载完整元数据
  5. 前端渲染搜索结果,高亮匹配的文本片段

三、安装与快速开始

3.1 环境要求

最低配置:

  • CPU:1 核
  • 内存:2 GB RAM
  • 存储:根据文档数量,建议 10 GB 以上
  • 操作系统:Linux、macOS、Windows(通过 Docker)

推荐配置:

  • CPU:2 核以上
  • 内存:4 GB RAM 以上
  • 存储:SSD 硬盘

3.2 Docker Compose 安装(推荐)

这是最简单的安装方式,适合大多数用户。

Step 1: 下载 docker-compose.yml

# 创建项目目录
mkdir -p ~/paperless-ngx
cd ~/paperless-ngx

# 下载官方 docker-compose.yml
curl -O https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docker/compose/docker-compose.postgres.yml
curl -O https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docker/compose/compose.env

Step 2: 配置环境变量

编辑 compose.env,修改以下配置:

# 数据库配置(默认即可)
PAPERLESS_DBENGINE=postgresql
PAPERLESS_DBNAME=paperless
PAPERLESS_DBUSER=paperless
PAPERLESS_DBPASS=paperless

# 时区设置(重要!)
PAPERLESS_TIME_ZONE=Asia/Shanghai

# 可选:设置管理员账号
PAPERLESS_ADMIN_USER=admin
PAPERLESS_ADMIN_PASSWORD=your_secure_password

# 可选:启用 OCR 语言包(默认只有英文)
PAPERLESS_OCR_LANGUAGE=eng+chi_sim+chi_tra

Step 3: 启动服务

docker compose -f docker-compose.postgres.yml up -d

Step 4: 访问 Web 界面

打开浏览器,访问 http://localhost:8000,使用设置的管理员账号登录。

3.3 一键安装脚本

Paperless-ngx 提供了交互式安装脚本:

bash -c "$(curl -L https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/install-paperless-ngx.sh)"

脚本会引导你完成:

  • 选择安装目录
  • 配置端口
  • 选择数据库(PostgreSQL 或 MariaDB)
  • 配置时区和语言

3.4 最简运行示例

使用默认配置快速启动(SQLite 数据库):

# 下载简化版 docker-compose.yml
curl -O https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docker/compose/docker-compose.sqlite.yml

# 启动服务
docker compose -f docker-compose.sqlite.yml up -d

# 查看日志
docker compose -f docker-compose.sqlite.yml logs -f

上传第一个文档:

# 方法 1:通过 Web 界面上传
# 访问 http://localhost:8000,点击"上传"按钮

# 方法 2:通过 consume 目录(适合批量导入)
# 将文件复制到容器的 consume 目录
docker cp my_document.pdf paperless-ngx-web:/usr/src/paperless/consume/

四、使用方法与实战

4.1 基础用法

1. 文档上传

  • Web 界面上传:支持拖拽、多选,可以批量上传
  • 邮件导入:配置 IMAP 邮箱,自动拉取邮件附件
  • Consume 目录:将文件放入 consume 目录,自动导入
  • API 上传:通过 REST API 集成到其他系统

2. 文档搜索

Paperless-ngx 提供强大的搜索功能:

  • 基础搜索:输入关键词,搜索标题和内容
  • 高级搜索语法:
    • tag:发票 - 搜索标签为"发票"的文档
    • correspondent:电力公司 - 搜索发件人为"电力公司"的文档
    • type:合同 - 搜索指定文档类型
    • date:2024-01 - 搜索 2024 年 1 月的文档
    • is:not_tagged - 搜索未打标签的文档
    • content:水电费 - 搜索内容包含"水电费"的文档

3. 自动化规则

在"设置"→“匹配规则"中配置自动化规则,例如:

  • 如果发件人是"XX 电力”,自动添加标签"水电费"
  • 如果文件名包含"发票",自动设置为"发票"类型
  • 如果内容包含"合同",自动添加到"合同"对应人

4.2 进阶用法

1. 集成 Scanner(扫描仪)

如果你有支持网络扫描的扫描仪,可以配置 SMB/NFS 共享,让扫描仪直接扫描到 consume 目录。

2. 使用 API 自动化

Paperless-ngx 提供完整的 REST API,可以通过 API Token 进行认证:

# 获取 API Token(在用户设置中生成)

# 上传文档
curl -X POST http://localhost:8000/api/documents/post_document/ \
  -H "Authorization: Token YOUR_TOKEN" \
  -F "document=@/path/to/document.pdf" \
  -F "title=我的文档" \
  -F "correspondent=1" \
  -F "tags=1,2,3"

3. 配置 Nginx 反向代理

在生产环境中,建议使用 Nginx 作为反向代理:

server {
    listen 80;
    server_name paperless.example.com;

    location / {
        proxy_pass http://localhost:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

4. 数据备份

定期备份数据库和文档文件:

# 备份脚本示例
#!/bin/bash
BACKUP_DIR=/path/to/backup
DATE=$(date +%Y%m%d)

# 备份 PostgreSQL 数据库
docker exec paperless-ngx-db pg_dump -U paperless paperless > $BACKUP_DIR/db_$DATE.sql

# 备份文档文件
tar -czf $BACKUP_DIR/media_$DATE.tar.gz /path/to/paperless/media

# 备份配置文件
tar -czf $BACKUP_DIR/config_$DATE.tar.gz /path/to/paperless/compose.env

4.3 实际项目示例

场景:家庭文档管理系统

需求:

  • 管理家庭的水电费、物业费等账单
  • 归档保险单、医疗记录等重要文件
  • 支持多用户(家庭成员)访问

实施步骤:

  1. 部署 Paperless-ngx:使用 Docker Compose 部署,配置 PostgreSQL
  2. 配置匹配规则:
    • 发件人包含"电力公司" → 标签"水电费"
    • 发件人包含"物业" → 标签"物业费"
    • 文件名包含"保险" → 类型"保险单"
  3. 设置定期备份:使用 cron 定时执行备份脚本
  4. 配置邮件导入:设置 IMAP 邮箱,自动导入账单邮件的附件
  5. 创建家庭成员账号:为每个家庭成员创建账号,设置合适的权限

五、常见问题与解决方案

5.1 安装失败

问题:Docker 镜像拉取失败

错误信息:Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled

解决方案:

  • 配置 Docker 镜像加速器(如使用腾讯云、阿里云镜像加速)
  • 检查网络连接,确保可以访问 Docker Hub
  • 尝试手动拉取镜像:docker pull ghcr.io/paperless-ngx/paperless-ngx:latest

问题:PostgreSQL 无法启动

错误信息:FATAL: password authentication failed for user "paperless"

解决方案:

  • 检查 compose.env 中的数据库密码配置
  • 确保 PostgreSQL 容器和 Web 容器使用相同的环境变量文件
  • 删除卷并重新创建:docker compose down -v && docker compose up -d

5.2 运行时错误

问题:OCR 识别失败

错误信息:ERROR: Failed to OCR document

可能原因:

  • 内存不足(OCR 需要较多内存)
  • 文档格式不支持
  • Tesseract 语言包未安装

解决方案:

  • 增加 Docker 容器的内存限制
  • 检查文档格式,确保是支持的格式(PDF、图片)
  • 在 compose.env 中配置 PAPERLESS_OCR_LANGUAGE,安装所需语言包

问题:搜索结果不准确

可能原因:

  • Tantivy 索引未正确更新
  • 文档内容未正确提取

解决方案:

# 重建搜索索引
docker exec -it paperless-ngx-web python3 manage.py document_index reindex

5.3 性能问题

问题:文档处理速度慢

解决方案:

  • 启用 GPU 加速(需要配置 CUDA 和相应的 Docker 镜像)
  • 增加 Celery worker 数量:在 docker-compose.yml 中设置 PAPERLESS_TASK_WORKERS=4
  • 使用更快的存储(SSD)
  • 限制同时处理的文档数量

问题:Web 界面加载慢

解决方案:

  • 配置 Nginx 缓存
  • 启用 Gzip 压缩
  • 使用 CDN 加速静态资源

5.4 兼容性问题

问题:某些 PDF 无法处理

可能原因:

  • PDF 加密或密码保护
  • PDF 版本过旧或过新
  • 损坏的 PDF 文件

解决方案:

  • 使用工具(如 qpdf)移除密码保护:qpdf --password=PASSWORD --decrypt input.pdf output.pdf
  • 尝试将 PDF 转换为图像,再重新生成 PDF
  • 检查 PDF 是否损坏:pdfinfo input.pdf

问题:中文 OCR 识别率低

解决方案:

  • 确保安装了中文语言包:PAPERLESS_OCR_LANGUAGE=chi_sim+chi_tra+eng
  • 提高 OCR 精度:设置 PAPERLESS_OCR_MODE=force(强制 OCR,即使已有文本层)
  • 使用更高质量的扫描图像(300 DPI 以上)

六、总结

Paperless-ngx 是一个功能强大、社区活跃的开源文档管理系统,非常适合个人和小团队使用。其核心价值在于:

  1. 完整的文档处理流水线:从上传到 OCR 识别、索引、搜索,一气呵成
  2. 现代化的技术栈:Django + Angular + Tantivy,性能和可维护性兼顾
  3. 灵活的部署方式:Docker、裸机、云端,随心选择
  4. 强大的搜索能力:基于 Tantivy 的全文搜索,支持复杂查询
  5. 活跃的社区:作为 Paperless-ng 的官方继任者,拥有持续的维护和丰富的文档

不足之处:

  • 对硬件资源有一定要求(尤其是 OCR 处理)
  • 移动端界面体验一般(正在改进中)
  • 高级功能(如工作流、自动化)相对简单

未来展望:

根据 GitHub 路线图和社区讨论,Paperless-ngx 未来可能加入:

  • 更强大的自动化工作流引擎
  • AI 辅助的文档分类和实体提取
  • 改进的移动端体验
  • 支持更多文档格式(如 EML、MSG)

推荐理由:

如果你正在寻找一个自托管的文档管理解决方案,Paperless-ngx 绝对值得尝试。它不仅能帮你摆脱纸质文档的困扰,还能通过数字化和智能化手段,让你的文档管理更加高效、有序。

资源链接:

  • 官方文档:https://docs.paperless-ngx.com/
  • GitHub 仓库:https://github.com/paperless-ngx/paperless-ngx
  • Docker Hub:https://hub.docker.com/r/paperlessngx/paperless-ngx
  • 社区论坛:https://github.com/paperless-ngx/paperless-ngx/discussions
  • Matrix 聊天室:https://matrix.to/#/#paperless:matrix.org

希望这篇指南能帮助你快速上手 Paperless-ngx。如果你有任何问题或建议,欢迎在评论区留言!