在文档翻译相关的业务场景中,把PDF翻译能力封装成一个内部微服务是常见需求。这篇文章分享一个基于Python+Flask的轻量级实现方案,支持文件上传、调用外部翻译API、返回翻译后的PDF下载链接。代码可直接运行,适合作为项目原型或内部工具使用。

前言

我们团队经常需要把客户发来的英文/日文/德文PDF文档翻译成中文,再分发出去。人工操作不仅慢,而且容易在复制粘贴过程中破坏原排版。于是我用Flask搭了一个简单的PDF翻译服务,核心逻辑是:

  1. 接收PDF文件上传;
  2. 调用第三方PDF翻译API;
  3. 等待翻译完成;
  4. 返回可下载的翻译后文件URL。

整个服务不到200行代码,部署方便。

环境准备

  • Python 3.10+
  • Flask
  • Requests
  • python-dotenv(用于管理环境变量)
pip install flask requests python-dotenv

项目结构

pdf-translate-service/
├── app.py
├── .env
├── uploads/
└── outputs/

核心代码

app.py

import os
import time
import uuid
import requests
from flask import Flask, request, jsonify, send_file
from dotenv import load_dotenv

load_dotenv()

app = Flask(__name__)

UPLOAD_FOLDER = "uploads"
OUTPUT_FOLDER = "outputs"
TRANSLATE_API_URL = os.getenv("TRANSLATE_API_URL", "https://api.example.com/translate")
API_KEY = os.getenv("API_KEY", "")

os.makedirs(UPLOAD_FOLDER, exist_ok=True)
os.makedirs(OUTPUT_FOLDER, exist_ok=True)


@app.route("/upload", methods=["POST"])
def upload_file():
    """接收PDF文件上传并提交翻译任务"""
    if "file" not in request.files:
        return jsonify({"error": "No file part"}), 400

    file = request.files["file"]
    if file.filename == "":
        return jsonify({"error": "No selected file"}), 400

    # 仅允许PDF
    if not file.filename.lower().endswith(".pdf"):
        return jsonify({"error": "Only PDF files are supported"}), 400

    # 保存上传文件
    task_id = str(uuid.uuid4())
    upload_path = os.path.join(UPLOAD_FOLDER, f"{task_id}.pdf")
    file.save(upload_path)

    # 获取语言参数
    source_lang = request.form.get("source_lang", "auto")
    target_lang = request.form.get("target_lang", "zh")

    # 提交翻译任务
    with open(upload_path, "rb") as f:
        resp = requests.post(
            TRANSLATE_API_URL,
            files={"file": f},
            data={
                "source_lang": source_lang,
                "target_lang": target_lang,
                "api_key": API_KEY,
            },
            timeout=30,
        )

    if resp.status_code != 200:
        return jsonify({"error": "Translation API error", "detail": resp.text}), 502

    result = resp.json()
    task_info = {
        "task_id": task_id,
        "status": "pending",
        "api_task_id": result.get("task_id"),
    }

    return jsonify(task_info), 202


@app.route("/status/<task_id>", methods=["GET"])
def check_status(task_id):
    """查询翻译任务状态"""
    # 实际项目中应存储任务状态到Redis/数据库
    api_task_id = request.args.get("api_task_id")
    if not api_task_id:
        return jsonify({"error": "api_task_id required"}), 400

    resp = requests.get(
        f"{TRANSLATE_API_URL}/status",
        params={"task_id": api_task_id, "api_key": API_KEY},
        timeout=10,
    )

    return jsonify(resp.json())


@app.route("/download/<task_id>", methods=["GET"])
def download_file(task_id):
    """下载翻译完成的PDF"""
    output_path = os.path.join(OUTPUT_FOLDER, f"{task_id}_translated.pdf")

    # 模拟轮询等待文件就绪(实际应用应使用任务队列)
    for _ in range(30):
        if os.path.exists(output_path):
            return send_file(output_path, as_attachment=True)
        time.sleep(1)

    return jsonify({"error": "File not ready"}), 404


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, debug=True)

.env

TRANSLATE_API_URL=https://api.example.com/translate
API_KEY=your_api_key_here

代码说明

上传接口 /upload:接收multipart/form-data格式的PDF文件,保存到本地后提交给翻译API。返回task_id和api_task_id供后续查询。

状态查询接口 /status/<task_id>:轮询翻译API的任务状态。实际生产环境中,建议把状态写入Redis或数据库,而不是依赖请求参数传递。

下载接口 /download/<task_id>:返回翻译完成的PDF文件。示例中用了简单的本地轮询,生产环境建议用Celery或RQ处理异步任务。

运行效果

启动服务:

python app.py

用curl测试上传:

curl -X POST http://127.0.0.1:5000/upload \
  -F "file=@sample.pdf" \
  -F "source_lang=en" \
  -F "target_lang=zh"

返回示例:

{
  "task_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "status": "pending",
  "api_task_id": "task_12345"
}

可扩展方向

  1. 异步任务队列:用Celery+Redis替换本地轮询,提升并发能力;
  2. 文件存储:大文件上传到OSS/S3,避免本地磁盘瓶颈;
  3. 进度推送:通过WebSocket或SSE向客户端实时推送翻译进度;
  4. 多语言支持:把源语言和目标语言扩展为可配置列表;
  5. 日志与监控:增加结构化日志和Prometheus指标,方便排查问题。

总结

这个Flask微服务虽然简单,但已经覆盖了PDF翻译场景的核心链路:上传、翻译、查询、下载。对于内部工具或原型验证来说足够用了。如果要投入生产,重点是把异步处理和状态持久化做好,避免大文件翻译阻塞主线程。

对于没有自己API资源的开发者,也可以直接使用现成的在线PDF翻译服务,把这篇文章的思路作为前端或内部系统集成的参考。

标签:PDF翻译、Python、Flask、AI翻译、后端开发

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐