FastAPI调用Ghostscript处理PDF后无法读取提取文本问题排查
问题根因定位
你遇到的PDF损坏、pdftoppm报错核心原因是FastAPI接口中保存上传的PDF文件后,没有主动关闭文件句柄,导致内存缓冲区的内容没有完全写入磁盘,Ghostscript读取的是不完整的损坏PDF文件,所以处理后的单页PDF全白、文本提取只有\x0c,直接提取原文件也会报找不到xref表、trailer字典的错误。Notebook里是操作本地已经写完的完整文件,所以不会触发这个问题。
修复方案
修改myapp.py的文件保存逻辑,确保文件完全写入磁盘后再调用Ghostscript处理,推荐使用with上下文自动管理文件句柄:
def getTypeAheads(documentType: str = Form(...),file: UploadFile = File(...)): if allowed_file(file.filename): logging.info("Is allowed file.") # 用with上下文,结束后自动关闭文件句柄,强制把缓冲区内容刷入磁盘 with open(file.filename, 'wb') as f_dest: shutil.copyfileobj(file.file, f_dest) #strip to one page only outfile_name = f"tmp_{file.filename}" subprocess.check_output(['gs', '-dBATCH', '-dNOPAUSE', '-dSAFER', '-dFirstPage=1', '-dLastPage=1', '-sDEVICE=pdfwrite', f'-sOUTPUTFILE={outfile_name}', file.filename]) logging.info("file saved with 1 page.") data = numberExtractor.start_extraction(outfile_name) logging.info("file extracted, deleting now.") os.remove(file.filename) os.remove(outfile_name) return data
如果不想用上下文写法,也可以手动调用flush和关闭逻辑:
f_dest = open(file.filename, 'wb') shutil.copyfileobj(file_object, f_dest) # 手动刷入缓冲区+关闭文件 f_dest.flush() os.fsync(f_dest.fileno()) f_dest.close()
补充排查验证点
如果修改后还有问题,可以按以下步骤排查:
- 临时注释掉删除文件的代码,保存处理前后的PDF文件,手动打开验证是否正常,确认损坏发生在哪一步
- 捕获Ghostscript命令的stdout/stderr日志,确认Ghostscript处理时是否已经报PDF损坏的警告
- 验证文件名是否包含特殊字符(比如示例里的空格),可以用绝对路径避免路径解析错误
- Docker环境下额外检查运行用户的目录读写权限,确保临时文件可以正常写入和读取
内容的提问来源于stack exchange,提问作者winformatics
相关产品推荐
相关产品推荐

