基于FastAPI搭建PDF翻译微服务:从架构到部署(附完整代码)
前言最近在做一个企业内部文档中台项目需要把PDF翻译能力封装成微服务供前端、IM机器人、定时任务等多个消费者调用。调研了一圈发现市面上的方案要么太重直接部署商业软件要么太轻纯脚本无法水平扩展。最终选型是FastAPI PDFTranslator API Docker轻量、异步、易部署。本文分享完整的架构设计和代码实现读者可以直接复制使用。环境准备Python 3.10Docker Docker Compose可选用于部署依赖库pipinstallfastapi uvicorn httpx python-multipart aiofiles架构设计┌─────────────┐ ┌──────────────────┐ ┌─────────────────┐ │ 前端/客户端 │────→│ FastAPI微服务 │────→│ PDFTranslator │ │ /IM机器人 │ │ (翻译任务管理) │ │ 翻译API │ └─────────────┘ └──────────────────┘ └─────────────────┘ │ ↓ ┌──────────────────┐ │ Redis (可选) │ │ 任务队列/缓存 │ └──────────────────┘核心设计原则异步处理PDF翻译是IO密集型操作FastAPI的异步能力可以高效处理并发状态管理翻译任务异步执行客户端通过任务ID轮询进度容错设计网络异常时自动重试失败任务可重新触发实现步骤Step 1: 项目结构pdf-translate-service/ ├── main.py # FastAPI入口 ├── translator.py # 翻译核心逻辑 ├── models.py # Pydantic模型 ├── requirements.txt └── DockerfileStep 2: 数据模型定义# models.pyfrompydanticimportBaseModel,FieldfromtypingimportOptional,LiteralfromdatetimeimportdatetimefromenumimportEnumclassTaskStatus(str,Enum):PENDINGpendingPROCESSINGprocessingCOMPLETEDcompletedFAILEDfailedclassTranslateRequest(BaseModel):source_lang:strField(defaultauto,description源语言代码)target_lang:strField(...,description目标语言代码如 zh, en, de)webhook_url:Optional[str]Field(None,description完成后的回调URL)classTranslateTask(BaseModel):task_id:strstatus:TaskStatus source_lang:strtarget_lang:stroriginal_filename:strcreated_at:datetime completed_at:Optional[datetime]Nonedownload_url:Optional[str]Noneerror_message:Optional[str]NoneStep 3: 翻译核心逻辑# translator.pyimporthttpximportuuidimportasynciofrompathlibimportPathfromtypingimportOptional PDFTRANSLATOR_APIhttps://api.pdftranslator.org/v1/translateclassPDFTranslatorClient:PDFTranslator API 异步客户端def__init__(self,api_key:Optional[str]None):self.api_keyapi_key self.clienthttpx.AsyncClient(timeout300.0)asyncdeftranslate(self,file_path:Path,target_lang:str,source_lang:strauto)-dict: 异步翻译PDF文件 Args: file_path: PDF文件路径 target_lang: 目标语言代码 source_lang: 源语言代码auto表示自动检测 Returns: API响应字典包含翻译结果URL headers{}ifself.api_key:headers[Authorization]fBearer{self.api_key}data{source_lang:source_lang,target_lang:target_lang}withopen(file_path,rb)asf:files{file:(file_path.name,f,application/pdf)}responseawaitself.client.post(PDFTRANSLATOR_API,datadata,filesfiles,headersheaders)response.raise_for_status()returnresponse.json()asyncdefclose(self):awaitself.client.aclose()Step 4: FastAPI 主服务# main.pyimportuuidimportshutilfromdatetimeimportdatetimefrompathlibimportPathfromtypingimportDictfromfastapiimportFastAPI,File,UploadFile,HTTPException,BackgroundTasksfromfastapi.responsesimportFileResponsefrommodelsimportTranslateRequest,TranslateTask,TaskStatusfromtranslatorimportPDFTranslatorClient appFastAPI(titlePDF Translation Microservice)# 内存存储生产环境建议用Redis 持久化数据库tasks_db:Dict[str,TranslateTask]{}UPLOAD_DIRPath(./uploads)RESULT_DIRPath(./results)UPLOAD_DIR.mkdir(exist_okTrue)RESULT_DIR.mkdir(exist_okTrue)app.post(/translate,response_modelTranslateTask)asyncdefcreate_translate_task(background_tasks:BackgroundTasks,request:TranslateRequest,file:UploadFileFile(...)): 创建PDF翻译任务 - 接收PDF文件和翻译参数 - 返回任务ID客户端通过 /tasks/{task_id} 查询进度 ifnotfile.filename.endswith(.pdf):raiseHTTPException(400,detailOnly PDF files are supported)task_idstr(uuid.uuid4())upload_pathUPLOAD_DIR/f{task_id}_{file.filename}withopen(upload_path,wb)asf:contentawaitfile.read()f.write(content)taskTranslateTask(task_idtask_id,statusTaskStatus.PENDING,source_langrequest.source_lang,target_langrequest.target_lang,original_filenamefile.filename,created_atdatetime.now())tasks_db[task_id]task# 后台异步执行翻译background_tasks.add_task(process_translation,task_idtask_id,file_pathupload_path,target_langrequest.target_lang,source_langrequest.source_lang)returntaskasyncdefprocess_translation(task_id:str,file_path:Path,target_lang:str,source_lang:str):后台执行翻译任务tasktasks_db[task_id]clientPDFTranslatorClient()try:task.statusTaskStatus.PROCESSING# 调用翻译API带重试resultawaittranslate_with_retry(client,file_path,target_lang,source_lang)# 保存结果这里模拟下载翻译后的文件result_pathRESULT_DIR/f{task_id}_translated.pdfawaitdownload_result(result[download_url],result_path)task.statusTaskStatus.COMPLETED task.completed_atdatetime.now()task.download_urlf/download/{task_id}exceptExceptionase:task.statusTaskStatus.FAILED task.error_messagestr(e)finally:awaitclient.close()# 清理上传的原始文件iffile_path.exists():file_path.unlink()asyncdeftranslate_with_retry(client:PDFTranslatorClient,file_path:Path,target_lang:str,source_lang:str,max_retries:int3)-dict:带重试机制的翻译调用forattemptinrange(max_retries):try:returnawaitclient.translate(file_path,target_lang,source_lang)excepthttpx.HTTPStatusErrorase:ife.response.status_code500andattemptmax_retries-1:wait_time2**attempt# 指数退避awaitasyncio.sleep(wait_time)continueraiseraiseException(Max retries exceeded)asyncdefdownload_result(url:str,save_path:Path):下载翻译结果asyncwithhttpx.AsyncClient()asclient:responseawaitclient.get(url)response.raise_for_status()withopen(save_path,wb)asf:f.write(response.content)app.get(/tasks/{task_id},response_modelTranslateTask)asyncdefget_task_status(task_id:str):查询任务状态iftask_idnotintasks_db:raiseHTTPException(404,detailTask not found)returntasks_db[task_id]app.get(/download/{task_id})asyncdefdownload_translated_file(task_id:str):下载翻译后的PDFiftask_idnotintasks_db:raiseHTTPException(404,detailTask not found)tasktasks_db[task_id]iftask.status!TaskStatus.COMPLETED:raiseHTTPException(400,detailTask not completed yet)result_pathRESULT_DIR/f{task_id}_translated.pdfifnotresult_path.exists():raiseHTTPException(404,detailResult file not found)returnFileResponse(result_path,filenameftranslated_{task.original_filename},media_typeapplication/pdf)app.get(/health)asyncdefhealth_check():健康检查端点return{status:healthy,timestamp:datetime.now().isoformat()}if__name____main__:importuvicorn uvicorn.run(app,host0.0.0.0,port8000)Step 5: Docker 部署配置# Dockerfile FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . RUN mkdir -p uploads results EXPOSE 8000 CMD [uvicorn, main:app, --host, 0.0.0.0, --port, 8000]# docker-compose.ymlversion:3.8services:pdf-translate-api:build:.ports:-8000:8000volumes:-./uploads:/app/uploads-./results:/app/resultsenvironment:-PYTHONUNBUFFERED1restart:unless-stoppedhealthcheck:test:[CMD,curl,-f,http://localhost:8000/health]interval:30stimeout:10sretries:3运行效果启动服务docker-composeup-d提交翻译任务curl-XPOSThttp://localhost:8000/translate\-Ffiledocument.pdf\-Frequest{target_lang:zh}查询任务状态curlhttp://localhost:8000/tasks/{task_id}响应示例{task_id:550e8400-e29b-41d4-a716-446655440000,status:completed,source_lang:auto,target_lang:zh,original_filename:document.pdf,created_at:2026-07-28T10:30:00,completed_at:2026-07-28T10:32:15,download_url:/download/550e8400-e29b-41d4-a716-446655440000,error_message:null}生产环境建议持久化存储用PostgreSQL替代内存字典存储任务状态消息队列用Celery Redis处理大文件翻译避免阻塞API限流用FastAPI的依赖注入实现速率限制防止滥用监控集成Prometheus Grafana监控API健康度认证添加JWT或API Key认证保护翻译接口总结这套方案的核心价值在于轻量和可扩展单服务启动仅需几十MB内存异步架构天然支持高并发Docker化部署适配K8s等容器编排平台与PDFTranslator的免费API结合企业文档中台的翻译成本可以降到接近零完整代码已在上文给出直接复制即可运行。有问题欢迎在评论区讨论。标签PDF翻译、FastAPI、Python、微服务、Docker、AI翻译

相关新闻

pycharm连接mysql时报错

pycharm连接mysql时报错

#在URL后加上: ?serverTimezoneUTC&characterEncodingutf-8

2026/7/28 15:47:39阅读更多 →
数据通信基础(一)

数据通信基础(一)

数据通信基础(一) 1.数据通信基本概念 2.数据通信计算 3.通信传输介质 4.数据调制与编码 1.数据通信基本概念 考点1: 信源:信号的产生物(发送端) 信道:通信的通道,是信号传输的媒介 信宿:信号的接收(接收端) 数字信号:是以某一瞬间的状态表示它们传送的消息,…

2026/7/28 15:47:39阅读更多 →
2026年大模型选型指南:不聊跑分,只讲场景和落地无标题】

2026年大模型选型指南:不聊跑分,只讲场景和落地无标题】

今年的模型格外火,模型跑分各种评论一堆一堆,真要选的时候还是不知道怎么定。 换模型改代码这个事,干过的都懂——改地址、改参数、改返回解析,一折腾就是半天,还得重新测一遍。 这篇不是测评报告,也不是源…

2026/7/28 15:47:39阅读更多 →
哪个 AI 写小说软件好用?10 款写小说工具网文作者实测,附避坑指南

哪个 AI 写小说软件好用?10 款写小说工具网文作者实测,附避坑指南

大家好,我是一个在网文圈扑腾了几年的老码字机了~ 每天深夜对着文档卡文、为了全勤奖硬熬字数、写到多线剧情时脑子突然卡住,这些痛苦我都太熟了。尤其是长篇小说连载到中后期,人物线、感情线、伏笔线全挤在一起,手放在键盘上&am…

2026/7/28 16:53:53阅读更多 →
SVGEdit终极指南:3步掌握浏览器免费SVG编辑器

SVGEdit终极指南:3步掌握浏览器免费SVG编辑器

SVGEdit终极指南:3步掌握浏览器免费SVG编辑器 【免费下载链接】svgedit Powerful SVG-Editor for your browser 项目地址: https://gitcode.com/gh_mirrors/sv/svgedit 想要在浏览器中免费创建和编辑专业矢量图形吗?SVGEdit就是你的完美解决方案&…

2026/7/28 16:53:53阅读更多 →
运用Statement技术实现jdbc的增删查该操作(很基础的一种)

运用Statement技术实现jdbc的增删查该操作(很基础的一种)

首先让大家看一下我定义的Student这个类里面有啥方便大家理解后续代码 package JDBC.Bigdata.Student;import java.io.File;public class Student {public int getSno() {return Sno;}public void setSno(int sno) {Sno sno;}public String getSname() {return Sname;}public …

2026/7/28 16:53:53阅读更多 →
嘎嘎降AI和PaperPass哪个降AI更稳:2026年降AI达标率完整对比测试

嘎嘎降AI和PaperPass哪个降AI更稳:2026年降AI达标率完整对比测试

嘎嘎降AI和PaperPass哪个降AI更稳:2026年降AI达标率完整对比测试 总有人问嘎嘎降AI和PaperPass对比,这篇把主流几款对比清楚。 综合推荐嘎嘎降AI(www.aigcleaner.com),4.8元,99.26%达标率。不同需求有不同…

2026/7/28 16:53:53阅读更多 →
AI智能体技术:如何将静态文档转化为动态知识伙伴

AI智能体技术:如何将静态文档转化为动态知识伙伴

1. 项目概述:当文档遇上AI智能体去年整理公司知识库时,我发现一个触目惊心的事实:我们耗费三个月搭建的文档系统,实际使用率不足15%。这些凝结着团队经验的PDF、PPT和Word文档,就像被施了沉睡魔咒般躺在服务器里。直到…

2026/7/28 16:53:53阅读更多 →
3 连接mysql 数据库 进行数据的存储和读取

3 连接mysql 数据库 进行数据的存储和读取

1下载node 连接模块npm i mysql -s2 在 src 下创建 conf 文件夹 用于存放配置文件 新建db.js通过环境参数的不同进行线上和线下配置const env process.env.NODE_ENV//环境参数let MYSQL_CONFif (env dev) {MYSQL_CONF {host: localhost,user: root,password: ,port: 3306,d…

2026/7/28 16:51:53阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/28 4:06:39阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/28 2:08:06阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/28 1:38:28阅读更多 →
告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生 【免费下载链接】OmenSuperHub Control Omen laptop performance, fan speeds, and keyboard lighting, and unlock power limits. 项目地址: https://gitcode.com/gh_mirrors/om/OmenSuperHub 你是否也曾为官方Om…

2026/7/28 0:00:29阅读更多 →
RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

做 RAG 的人应该都踩过这个致命的坑:把几百页的财报、法规、技术手册扔给向量库,问一个具体问题,搜出来的全是沾边但没用的内容 —— 关键信息要么被硬切块拆碎了,要么藏在几十条结果的最下面。语义相似≠真正相关,这个…

2026/7/28 0:00:29阅读更多 →
抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

2026年做短视频运营,从抖音上扒文案早就不是偷偷抄笔记的事了。我刚开始做内容的时候,每天刷半小时抖音,手动把爆款视频的口播敲进备忘录,一条2分钟的视频得花十来分钟,碰到语速快的还要反复回听。后来试了一圈工具&am…

2026/7/28 0:00:29阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/27 16:57:54阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/28 3:17:03阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/28 2:35:58阅读更多 →