PDF文档转换失败怎么处理:超时、重试与7天时效下载链接管理
pdf-doc-convert-fail-retry-3275 # PDF文档转换失败怎么处理:超时、重试与7天时效下载链接管理
> 接口:PDF文档转换 · 接入点 `3275-1` / `3275-2` / `3275-3` · 付费 · POST/GET · JSON
> 适用人群:已接入用户、运维工程师
> 阅读时间:约 5 分钟
> 最后实测核对:2026-09-07
---
## 核心要点
- 常见失败原因:文件格式不支持、超过 100MB、网络超时、AppKey 余额不足、task_id 无效。
- 重试策略:指数退避(间隔 2s → 4s → 8s),最多重试 3 次,避免雪崩。
- download_url 7 天时效必须在代码层管理,不能依赖外部链接长期有效。
---
## 失败类型与排查
### 1. 上传阶段失败(3275-1 返回 ret_code=-1)
**常见原因:**
| 原因 | 排查方法 |
|------|---------|
| AppKey 无效或余额不足 | 登录控制台查看账户状态和资源包用量 |
| 文件格式不是 PDF | 检查文件后缀和 MIME type,用 `file` 命令或浏览器确认 |
| 文件超过 100MB | 打印文件大小,必要时先压缩或拆分 |
| file_url 无法访问 | 确认 URL 可公开访问(无鉴权、无 403),用浏览器打开测试 |
| base64 编码错误 | 检查 base64 字符串是否完整、有无换行符干扰 |
---
### 2. 轮询阶段失败(3275-2 返回 state=failed)
**常见原因:**
| 原因 | 排查方法 |
|------|---------|
| PDF 内容无法解析(加密、损坏) | 尝试用本地 PDF 阅读器打开,确认文件完整 |
| 纯图片 PDF(无文字层) | 接口对扫描版 PDF 不支持有效转换,`remark` 会提示 |
| 服务器端解析超时 | 大文件(>50页)可能需要较长时间,适当延长轮询上限 |
| task_id 已过期或被清理 | 调用 3275-3 查询历史记录,确认 task_id 是否存在 |
---
### 3. 下载阶段失败
**常见原因:**
| 原因 | 排查方法 |
|------|---------|
| download_url 已过期(超过 7 天) | 查 3275-3 历史记录,若仍在窗口内重新获取链接 |
| OSS 链接临时不可达 | 等几分钟重试下载,OSS 偶发抖动 |
| 下载后文件损坏 | 检查文件头,确认是有效 Markdown 或 docx |
---
## 重试策略:指数退避实现
```python
import time
import requests
def poll_with_retry(task_id: str, app_key: str, max_retries: int = 3, base_delay: float = 2.0):
"""
带指数退避的轮询,处理网络抖动导致的偶发失败
"""
for attempt in range(max_retries):
try:
resp = requests.post(
"https://route.showapi.com/3275-2",
params={"appKey": app_key},
data={"task_id": task_id},
timeout=10,
)
body = resp.json()["showapi_res_body"]
if body["state"] == "success":
return body["download_url"]
if body["state"] == "failed":
return None # 失败不重试,由调用方决定重新上传
# preparing / processing:继续轮询
return body["state"]
except (requests.Timeout, requests.ConnectionError) as e:
if attempt < max_retries - 1:
delay = base_delay * (2 ** attempt)
print(f"网络异常,{delay}s 后重试...")
time.sleep(delay)
else:
raise RuntimeError(f"轮询失败,已重试 {max_retries} 次") from e
return None
```
关键点:
- 网络错误(超时、连接断开)才重试,业务失败(state=failed)不重试。
- 指数退避避免密集请求触发限流。
- max_retries=3、base_delay=2 是经验值,可根据实际调整。
---
## 7 天时效下载链接的管理策略
这是最容易踩的坑:把 download_url 存进数据库当永久链接,7 天后调用发现 404。
**正确做法:转换完成后立即下载,存储到自有存储。**
```python
import requests
from pathlib import Path
def fetch_and_store(download_url: str, store_dir: Path, filename: str):
"""下载转换结果并存储到自有位置"""
store_dir.mkdir(parents=True, exist_ok=True)
local_path = store_dir / filename
resp = requests.get(download_url, timeout=30)
resp.raise_for_status()
local_path.write_bytes(resp.content)
return str(local_path)
```
**进阶:建立定期刷新机制**
如果业务需要长期保留转换结果,可以写一个定时任务(如每天一次):
1. 查 3275-3 历史记录,找出即将过期的任务。
2. 重新调用 3275-2 获取新的 download_url。
3. 下载并覆盖本地副本。
---
## 历史记录查询(3275-3)的使用
```python
def query_history(app_key: str, page: int = 1):
resp = requests.post(
"https://route.showapi.com/3275-3",
params={"appKey": app_key},
data={"page": str(page)},
timeout=10,
)
body = resp.json()["showapi_res_body"]
if body["ret_code"] != 0:
raise RuntimeError(f"查询失败: {body.get('remark')}")
tasks = body.get("contentlist", [])
print(f"共 {body['allNum']} 条记录,当前第 {body['currentPage']}/{body['allPages']} 页")
for t in tasks:
print(f" task_id={t['task_id']} state={t['state']} ct={t['ct']}")
return tasks
```
`contentlist` 每条记录包含 `task_id`、`state`、`ct`(上传时间)、`file_url`、`download_url`,注意这些 URL 同样有 7 天时效。
---
## FAQ
**Q1:state=failed 时能不能用同一个 task_id 重新查询得到新结果?**
不能。failed 状态的 task_id 无法恢复,需要重新上传 PDF 生成新 task_id。
**Q3:download_url 过期了还能从 3275-3 历史查询里拿到吗?**
可以,3275-3 返回的 download_url 和 3275-2 一样有 7 天时效。如果任务已超过 7 天,历史记录里的链接也已过期,只能重新转换。
**Q4:怎么知道哪些 PDF 适合这个接口?**
先用小文件(≤10页、含文字层)测试,确认输出格式符合预期后再批量接入。扫描件、加密 PDF、超大文件(>50MB)建议先做前置过滤。
**Q5:接口有调用频率限制吗?**
接口文档未公开限流规则。实测中正常速率(每秒 1~2 次)无问题,建议生产环境加并发控制(如令牌桶),保守起见单 AppKey 不超过 10 QPS。
---
## 下一步阅读
- [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文档转换](https://www.showapi.com/guides/pdf-doc-convert-knowledge-base-3275)
---
*本系列共 5 篇:查看[PDF文档转换指南总目录](https://www.showapi.com/guides/pdf-doc-convert-guides-3275)*