原创

Flask 实现 PDF 上传与文本提取接口

围绕 PDF 上传和文本提取整理 Flask 接口示例,补充输入限制、异常反馈与开发部署范围,并说明扫描件和阅读顺序的限制。

接口目标与适用范围

原记录使用 Flask 接收 PDF 文件,并用 pdfminer 提取文字。它更适合作为文本提取接口的入门示例,尚不足以称为完整的生产部署方案。

下面改用 pdfminer.six 的高层 API,补上上传上限、错误分类和开发启动参数。示例需要安装 Flask 与 pdfminer.six,正式使用时应固定并记录实际测试过的依赖版本。

接口示例

from flask import Flask, jsonify, request
from pdfminer.high_level import extract_text
from pdfminer.pdfdocument import PDFPasswordIncorrect
from pdfminer.pdfparser import PDFSyntaxError

app = Flask(__name__)
app.config["MAX_CONTENT_LENGTH"] = 10 * 1024 * 1024

@app.errorhandler(413)
def too_large(error):
    return jsonify(error="file_too_large"), 413

@app.post("/upload")
def upload_pdf():
    upload = request.files.get("file")
    if upload is None or not upload.filename:
        return jsonify(error="file_required"), 400
    if not upload.filename.lower().endswith(".pdf"):
        return jsonify(error="pdf_required"), 400
    try:
        text = extract_text(upload.stream)
    except PDFPasswordIncorrect:
        return jsonify(error="encrypted_pdf_not_supported"), 422
    except PDFSyntaxError:
        return jsonify(error="invalid_pdf"), 422
    except Exception:
        app.logger.exception("PDF extraction failed")
        return jsonify(error="extraction_failed"), 500
    return jsonify(text=text, empty=not bool(text.strip())), 200

if __name__ == "__main__":
    app.run(host="127.0.0.1", port=5000, debug=False)

原文的 debug=Flask 将类对象传给了调试参数,本次改为明确的布尔值。扩展名检查仅用于快速拒绝明显不符的请求,不能证明文件内容安全或有效。

上传限制是整个请求体上限,包含 multipart 开销,并非严格的 PDF 净文件大小配额。示例也尚未实现解析进程隔离、执行时间限制、并发限制和完整的损坏文件错误分类;它仍应在受控环境测试。

如何判断提取是否有价值

建议建立一小组固定 PDF 样本:普通文本、双栏排版、表格、扫描件、空白页、加密文件以及损坏文件。对每个样本保存预期观察点,而不是只检查 HTTP 状态码。

检查维度 观察内容
文本完整性 标题、正文和页码是否缺失或重复
阅读顺序 双栏是否交叉,页眉页脚是否混入正文
表格结构 行列关系是否丢失,能否支持后续用途
空文本 是空白页,还是只有图片、需要 OCR
资源消耗 文件大小、页数、处理时间和内存

本次没有执行这些样本实验,因此不提供识别率或性能数字。若后续用于 RAG,应先证明解析文本能够保持所需信息,再讨论切分和检索。

开发运行与部署

Flask 内置服务用于本地开发,不应直接作为正式部署服务。部署时使用合适的 WSGI 服务,设置明确的请求与处理资源限制;上述同步解析示例在大文件或并发场景下还需要独立评估。

参考

正文到此结束