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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 08:09:03