技术博客
PDF文档转换:5分钟完成异步上传与结果下载

PDF文档转换:5分钟完成异步上传与结果下载

作者: 万维易源
2026-09-07
pdf-doc-convert-quickstart-3275
# PDF文档转换:5分钟完成异步上传与结果下载 > 接口:PDF文档转换 · 接入点 `3275-1` / `3275-2` · 付费(¥9.90起/12个月)· POST · JSON · 异步两步走 > 适用人群:新注册用户、初级开发者 > 阅读时间:约 6 分钟 > 最后实测核对:2026-09-07 --- ## 核心要点 - 接口**不直接返回转换内容**,上传后先拿到 `task_id`,再轮询获取 `download_url`。 - 单文件上限 **100MB**;`type=md` 输出 Markdown,`type=docx` 输出 Word。 - `download_url` 和 `file_url` 实效 **7 天**,过期需重新提交或查历史记录(`3275-3`)。 --- ## Why 这个接口 你有一份 PDF,想把内容转成 Markdown 丢进知识库做 RAG,或者转成 docx 给业务系统用。最土的做法是自己接 Tesseract OCR,精度差还难调;花钱买 SaaS OCR,按页计费贵且黑盒。 ShowAPI 的 PDF文档转换接口(apiCode=3275,万维易源自营)把这件事封装成 HTTP 调用:传文件、等任务完成、下载结果。返回的是标准 JSON,状态机清晰,代码量小。 --- ## What 前置条件 1. 在 [ShowAPI 控制台](https://www.showapi.com/console#/myApp) 注册账号并获取 AppKey。 2. 购买资源包(专用资源包 ¥9.90/12个月起,或充值通用资源包直接使用)。 3. 准备一份不超过 100MB 的 PDF 文件(本地文件、可访问的 URL、或 base64 字符串,三选一)。 --- ## How 完整流程(以 file_url 方式为例) ### 第 1 步:上传 PDF,获取 task_id ```bash curl -X POST "https://route.showapi.com/3275-1?appKey=YOUR_APPKEY" \ -H "content-type: multipart/form-data" \ -F "file_url=https://example.com/sample.pdf" \ -F "type=md" ``` **响应示例:** ```json { "showapi_res_code": 0, "showapi_res_body": { "ret_code": 0, "remark": "文件创建成功", "state": "preparing", "task_id": "54f9a8a59e8b", "file_name": "sample.pdf" } } ``` 关键判断:`ret_code == 0` 说明上传成功,`task_id` 是你之后轮询的依据。 --- ### 第 2 步:轮询结果,直到 state 不再是 preparing / processing ```bash # 每 2 秒轮询一次,直到 state 变为 success 或 failed curl -X POST "https://route.showapi.com/3275-2?appKey=YOUR_APPKEY" \ -d "task_id=54f9a8a59e8b" ``` **成功时响应:** ```json { "showapi_res_code": 0, "showapi_res_body": { "ret_code": 0, "remark": "成功", "state": "success", "download_url": "http://showapi-pub-shanghai.oss-cn-shanghai.aliyuncs.com/7day-delete/abc.md", "file_url": "http://showapi-pub-shanghai.oss-cn-shanghai.aliyuncs.com/7day-delete/abc.md" } } ``` **失败时 state 为 `failed`**,查看 `remark` 字段了解原因(常见:文件格式不支持、超出 100MB 限制)。 --- ### 第 3 步:下载结果文件 `download_url` 指向实际转换后的 `.md` 或 `.docx` 文件,下载后使用。 --- ## Python 完整示例(含轮询逻辑) ```python import time import requests APP_KEY = "YOUR_APPKEY" PDF_URL = "https://example.com/sample.pdf" BASE = "https://route.showapi.com" # Step 1: 上传 resp = requests.post( f"{BASE}/3275-1", params={"appKey": APP_KEY}, data={"file_url": PDF_URL, "type": "md"}, timeout=10, ) body = resp.json()["showapi_res_body"] if body["ret_code"] != "0": raise RuntimeError(f"上传失败: {body['remark']}") task_id = body["task_id"] print(f"task_id={task_id}, state={body['state']}") # Step 2: 轮询 for _ in range(30): # 最多轮询 30 次(约 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": print(f"转换成功!下载: {body['download_url']}") break if body["state"] == "failed": raise RuntimeError(f"转换失败: {body['remark']}") print(f" 进行中... state={body['state']}") else: raise TimeoutError("转换超时,请检查 PDF 大小或格式") ``` --- ## Node.js 完整示例 ```javascript const axios = require("axios"); const APP_KEY = "YOUR_APPKEY"; const PDF_URL = "https://example.com/sample.pdf"; async function convertPdf() { // Step 1: 上传 const uploadRes = await axios.post( "https://route.showapi.com/3275-1", null, { params: { appKey: APP_KEY }, data: new URLSearchParams({ file_url: PDF_URL, type: "md" }), timeout: 10000, } ); const { task_id, state } = uploadRes.data.showapi_res_body; console.log(`task_id=${task_id}, state=${state}`); // Step 2: 轮询 for (let i = 0; i < 30; i++) { await new Promise((r) => setTimeout(r, 2000)); const queryRes = await axios.post( "https://route.showapi.com/3275-2", null, { params: { appKey: APP_KEY }, data: new URLSearchParams({ task_id }), timeout: 10000, } ); const { state: st, download_url, remark } = queryRes.data.showapi_res_body; if (st === "success") { console.log(`转换成功!下载: ${download_url}`); return download_url; } if (st === "failed") throw new Error(`转换失败: ${remark}`); console.log(` 进行中... state=${st}`); } throw new Error("转换超时"); } convertPdf().catch(console.error); ``` --- ## 关键注意事项 1. **三选一上传方式**:`file_byte`(本地文件字节)、`file_url`(可下载链接)、`file_base64`(base64 字符串),三者任选其一,不能同时传多个。 2. **type 参数**:`md` 输出 Markdown,`docx` 输出 Word,默认 `md`。 3. **超时设置**:接入点 1 的 read_timeout 为 10s,建议代码中设 `timeout=10`;接入点 2/3 为 5s。 4. **7 天时效**:`download_url` 和 `file_url` 有效期 7 天,建议在代码中及时下载并缓存本地。 5. **文件大小**:超过 100MB 会失败,大文件建议先分割再分批上传。 --- ## FAQ **Q1:上传后一直返回 state=preparing 不动怎么办?** 通常说明服务正在处理队列中,正常情况 processing 会在几秒内出现。如果超过 30 秒仍无变化,可能是 PDF 过大或格式特殊,建议先用小文件测试连通性。 **Q2:下载链接 7 天后过期了还能重新获取吗?** 可以。调用历史记录查询接口(`3275-3`)查看该 `task_id` 的 `download_url`,若仍在 7 天窗口内可重新下载;已过期则需重新提交转换任务。 **Q3:ret_code=-1 怎么排查?** 先看 `remark` 字段的描述信息,常见原因:AppKey 无效、文件格式不支持、文件无法访问(file_url 方式)、参数缺失。 **Q4:想批量转换几十个 PDF 怎么办?** 本接口不支持同步批量,需要对每个文件单独调用上传接口,建议加个并发控制(如 Python 的 `concurrent.futures`)避免限流。 **Q5:怎么知道转换后的文件有多少页?** 转换后的 Markdown/docx 文件内容里可统计页码,但接口本身不直接返回页数。计费是按实际页数计算的,账单中可查看。 --- ## 下一步阅读 - [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) - [PDF文档转换失败怎么处理:超时、重试与7天时效下载链接管理](https://www.showapi.com/guides/pdf-doc-convert-fail-retry-3275) - [PDF转Markdown方案怎么选:自建 OCR、付费接口与 ShowAPI 三方对比](https://www.showapi.com/guides/pdf-doc-convert-compare-3275) --- *本系列共 5 篇:查看[PDF文档转换指南总目录](https://www.showapi.com/guides/pdf-doc-convert-guides-3275)*