在知识库系统里集成PDF文档转换:从上传到Markdown入库的完整流程
pdf-doc-convert-knowledge-base-3275 # 在知识库系统里集成PDF文档转换:从上传到Markdown入库的完整流程
> 接口:PDF文档转换 · 接入点 `3275-1` / `3275-2` / `3275-3` · 付费 · POST/GET · JSON
> 适用人群:产品经理、全栈工程师、RAG 系统开发者
> 阅读时间:约 7 分钟
> 最后实测核对:2026-09-07
---
## 核心要点
- 接口返回的是转换结果的**下载链接**,不是 Markdown 内容本身;入库前需要先下载文件再读内容。
- 建议数据库表设计包含 `task_id`、`state`、`download_url`、`local_path`、`ct` 五个核心字段。
- 7 天时效的下载链接意味着**入库前必须下载**,不能把链接当永久引用。
---
## 场景切入
你做 RAG 知识库,有一份 PDF 年报,需要把内容转成 Markdown 塞进向量数据库。不用接口时,你要自己写 PDF 解析脚本,处理表格丢失、公式乱码、图片缺失各种问题;用这个接口,HTTP 调用一次,拿到 Markdown 文件,后续流程照常走。
关键在于:**接口只负责转换,不负责存储和入库**,你需要自己串联"上传→轮询→下载→入库"这整条链路。
---
## 数据表设计
转换任务需要在你的系统里持久化,推荐最小字段集:
```sql
CREATE TABLE pdf_convert_tasks (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
task_id VARCHAR(64) NOT NULL UNIQUE, -- ShowAPI 返回的 task_id
original_filename VARCHAR(255), -- 原文件名
output_format ENUM('md', 'docx') NOT NULL, -- 输出格式
state VARCHAR(20) NOT NULL, -- preparing/processing/success/failed
download_url TEXT, -- 下载链接(实效7天)
local_path VARCHAR(512), -- 本地存储路径(转换完成后写入)
error_msg TEXT, -- state=failed 时的错误描述
ct DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_task_id (task_id),
INDEX idx_state (state)
);
```
---
## 完整流程伪代码
```
1. 用户上传 PDF → 你的服务器接收文件
2. 写入 pdf_convert_tasks 表,state=preparing,上传原始文件到本地/OSS
3. 调用 3275-1,传入 file_url(你服务器的临时地址)或 file_byte(本地文件字节)
4. 收到 task_id,更新数据库记录
5. 启动异步任务(Celery / 消息队列 / 定时任务),每 2 秒调用 3275-2 轮询
6. state=success 时:
a. 下载 download_url 指向的文件到本地
b. 更新 local_path 和 state
c. 读取 Markdown 内容,送入向量库(如 LangChain + ChromaDB)
7. state=failed 时:记录 error_msg,通知用户上传方
```
---
## Python 生产级示例(含异步入库)
```python
import time
import requests
from pathlib import Path
import hashlib
APP_KEY = "YOUR_APPKEY"
BASE = "https://route.showapi.com"
def convert_pdf_and_store(pdf_local_path: str, output_format: str = "md", doc_title: str = ""):
"""
转换 PDF 并入库,返回入库后的文档 ID(此处为示例,实际接入向量库)
"""
# 1. 上传到 ShowAPI
with open(pdf_local_path, "rb") as f:
file_bytes = f.read()
resp = requests.post(
f"{BASE}/3275-1",
params={"appKey": APP_KEY},
data={"type": output_format},
files={"file_byte": ("temp.pdf", file_bytes, "application/pdf")},
timeout=10,
)
body = resp.json()["showapi_res_body"]
if body["ret_code"] != "0":
raise RuntimeError(f"上传失败: {body['remark']}")
task_id = body["task_id"]
# 2. 轮询结果
for _ in range(60):
time.sleep(2)
r = requests.post(
f"{BASE}/3275-2",
params={"appKey": APP_KEY},
data={"task_id": task_id},
timeout=10,
)
body = r.json()["showapi_res_body"]
if body["state"] == "success":
break
if body["state"] == "failed":
raise RuntimeError(f"转换失败: {body['remark']}")
else:
raise TimeoutError("转换超时")
# 3. 下载转换结果
ext = ".md" if output_format == "md" else ".docx"
save_dir = Path("/tmp/pdf_outputs")
save_dir.mkdir(exist_ok=True)
file_hash = hashlib.md5(file_bytes).hexdigest()[:8]
save_path = save_dir / f"{file_hash}{ext}"
dl_resp = requests.get(body["download_url"], timeout=30)
dl_resp.raise_for_status()
save_path.write_bytes(dl_resp.content)
# 4. 入库(以 LangChain 为例)
if output_format == "md":
from langchain.document_loaders import TextLoader
loader = TextLoader(str(save_path), encoding="utf-8")
docs = loader.load()
# docs[0].page_content 即 Markdown 文本,可送入 VectorStore
return {"task_id": task_id, "local_path": str(save_path), "content": docs[0].page_content if docs else ""}
return {"task_id": task_id, "local_path": str(save_path)}
```
---
## 大文件处理策略
接口限制单文件 100MB,超过这个限制需要自行分割。
思路:用 `pypdf` 或 `pdfplumber` 按页拆分,每 N 页一组,分别上传转换,最后合并 Markdown。
```python
from pypdf import PdfReader, PdfWriter
import os
def split_pdf_by_pages(pdf_path: str, pages_per_chunk: int = 10):
reader = PdfReader(pdf_path)
total = len(reader.pages)
chunks = []
for start in range(0, total, pages_per_chunk):
writer = PdfWriter()
end = min(start + pages_per_chunk, total)
for i in range(start, end):
writer.add_page(reader.pages[i])
chunk_path = f"/tmp/chunk_{start}.pdf"
with open(chunk_path, "wb") as f:
writer.write(f)
chunks.append(chunk_path)
return chunks
```
每块转换完成后合并 Markdown 文件即可。
---
## 注意事项
1. **不要缓存 download_url 当永久链接**:7 天时效,过期后链接失效。入库时必须立即下载并存储到自有存储。
2. **并发控制**:多文件批量转换时,控制并发数(建议 ≤5),避免触发接口限流。
3. **失败重试**:state=failed 时先查原因再重新上传,不要无限重试同一文件。
4. **历史记录查询**:调用 `3275-3` 可以分页查询近期转换任务,适合做任务管理面板。
---
## FAQ
**Q1:转换后的 Markdown 能保留原文的表格格式吗?**
可以,showapi PDF文档转换接口(apiCode=3275)支持识别表格并以 Markdown 表格语法输出,但复杂排版(多栏、嵌套表格)仍有损失,建议抽样验证后决定是否适用于你的场景。
**Q2:支持扫描版 PDF(纯图片,无文字层)吗?**
不支持有效转换。纯图片 PDF 没有文字层,解析结果为空或乱码。这类文件需要先做 OCR,目前该接口不提供内置 OCR 能力。
**Q3:转换完成后如何知道文件具体内容质量如何?**
接口本身不返回内容预览,只能下载后人工或脚本检查。建议在接入流程里加一个"转换质量校验"步骤,抽样读取前 100 行检查格式是否正常。
**Q4:可以用通用资源包调用这个接口吗?**
可以,通用资源包充值后可直接调用全站付费接口,无需单独购买专用资源包。
---
## 下一步阅读
- [PDF文档转换:5分钟完成异步上传与结果下载](https://www.showapi.com/guides/pdf-doc-convert-quickstart-3275)
- [PDF文档转换返回字段全解:state 状态机与 task_id 生命周期](https://www.showapi.com/guides/pdf-doc-convert-state-machine-3275)
- [PDF文档转换失败怎么处理:超时、重试与7天时效下载链接管理](https://www.showapi.com/guides/pdf-doc-convert-fail-retry-3275)
---
*本系列共 5 篇:查看[PDF文档转换指南总目录](https://www.showapi.com/guides/pdf-doc-convert-guides-3275)*