You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask接收Curl上传文件后调用pdftotext的os.PathLike对象问题

解决Flask中调用pdftotext无需临时文件的方案

我完全理解你不想依赖临时文件的痛点——频繁读写存储确实会拖慢Lambda函数的性能。其实不用折腾模拟os.PathLike对象,pdftotext本身就支持通过标准输入(stdin)接收PDF内容,直接用管道传递数据就行,完全不需要落地文件。

核心思路

pdftotext的命令行参数里,把输入文件路径换成-,就表示从标准输入读取PDF数据;输出参数用-表示把提取的文本输出到标准输出(stdout)。这样我们可以通过subprocess的管道,直接把上传的文件bytes传给pdftotext,同时捕获它的输出。

代码实现

from flask import Flask, request
import subprocess

app = Flask(__name__)

@app.route('/', methods=['POST'])
def process_pdf():
    # 替换成你的pdftotext实际路径
    PDFTOTEXT_PATH = "/usr/bin/pdftotext"
    
    # 获取上传的文件对象
    uploaded_file = request.files['file']
    
    # 启动pdftotext进程,配置管道
    proc = subprocess.Popen(
        [PDFTOTEXT_PATH, "-layout", "-", "-"],
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        text=False  # 用bytes模式处理,避免编码问题
    )
    
    # 把上传文件的bytes传入stdin,同时获取输出和错误信息
    stdout, stderr = proc.communicate(input=uploaded_file.read())
    
    # 检查进程执行状态
    if proc.returncode != 0:
        return f"PDF处理失败: {stderr.decode('utf-8')}", 500
    
    # 返回提取后的文本(转成字符串)
    return stdout.decode('utf-8')

if __name__ == '__main__':
    app.run(debug=True)

为什么之前的方法会报错?

  • 直接把bytes传入subprocess的参数列表:命令行参数不允许包含null字节(PDF二进制内容里大概率有),所以触发ValueError: embedded null byte。
  • 转成字符串传参:大文件的字符串会超出系统允许的命令行参数长度上限,导致OSError: [Errno 7] Argument list too long。
  • 用BytesIO等包装:subprocess的参数只接受实际的文件路径字符串/os.PathLike对象,内存中的IO对象不被命令行工具识别,所以报错类型不匹配。

额外注意事项

  • 确认你的pdftotext版本支持从stdin读取:主流的xpdf/poppler版本的pdftotext都支持这个特性,如果是小众版本可以先在本地测试cat test.pdf | pdftotext -layout - -是否能正常输出文本。
  • 大文件处理:如果上传的PDF特别大,communicate会一次性把全部数据加载到内存,这时可以考虑分块写入stdin,但Lambda的内存限制内一般都没问题。

内容的提问来源于stack exchange,提问作者lawson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:46:23