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
相关产品推荐
相关产品推荐

