私有部署中,实现免费Word转PDF的一点思路

分享  收藏
8 / 1120

找一台没人用的老电脑,装个 Windows,装个 Microsoft Office,然后一个域名,一个免费 SSL 证书,再来一个隧道穿透工具,开发语言为 Python。通过 API 来提供格式转换服务,大家有没有兴趣来测试研究一下。

在下面的代码中,使用 win32com 库来执行 Word 到 PDF 的转换,因为它可以在已经安装 Microsoft Office 的 Windows 系统上运行。此外,添加一些 HTTP 状态码和错误消息以方便外部用户理解 API 的使用情况。

需要安装以下 Python 库:

  1. Flask
  2. Flask-RESTful
  3. python-dotenv
  4. pycryptodome
  5. requests
  6. os
  7. uuid
  8. shutil
  9. win32com
pip install flask flask-restful python-dotenv pycryptodome requests os uuid shutil pywin32

# 导入必要的库
from flask import Flask, request, send_file, after_this_request
from flask_restful import Api, Resource
from dotenv import load_dotenv
import os
import uuid
from Crypto.Hash import HMAC
from Crypto.Hash import SHA256
import shutil
import win32com.client

# 加载环境变量
load_dotenv()

# 获取环境变量
APP_KEY = os.getenv('APP_KEY')
SECRET_KEY = os.getenv('SECRET_KEY')

# 初始化 Flask 应用
app = Flask(__name__)
api = Api(app)

# 设置临时目录
TEMP_DIR = '/tmp'

# 定义验证请求的函数
def verify_request(req):
    # 获取请求头中的 AppKey、Sign
    app_key = req.headers.get('AppKey')
    sign = req.headers.get('Sign')

    # 验证 AppKey
    if app_key != APP_KEY:
        return False

    # 计算 HMAC-SHA256
    h = HMAC.new(SECRET_KEY.encode('utf-8'), digestmod=SHA256)
    h.update(req.data)

    # 验证 Sign
    if h.hexdigest() != sign:
        return False

    return True

# 定义处理 Word 文档的类
class DocHandler(Resource):
    # 处理 POST 请求
    def post(self):
        # 验证请求
        if not verify_request(request):
            # 如果请求不合法,返回错误信息
            return {'message': 'Invalid request'}, 401

        # 获取上传的 Word 文档
        doc_file = request.files['file']
        if doc_file is None:
            return {'message': 'No file is provided'}, 400

        # 生成唯一的文件名
        filename = str(uuid.uuid4())
        doc_path = os.path.join(TEMP_DIR, filename + '.docx')
        pdf_path = os.path.join(TEMP_DIR, filename + '.pdf')

        # 保存 Word 文档到临时目录
        doc_file.save(doc_path)

        # 将 Word 文档转换为 PDF 文件
        word = win32com.client.Dispatch('Word.Application')
        doc = word.Documents.Open(doc_path)
        doc.SaveAs(pdf_path, FileFormat=17)  # 17代表Word中的PDF格式
        doc.Close()
        word.Quit()

        # 返回 PDF 文件的路径
        return {'pdf_path': pdf_path}, 201

    # 处理 GET 请求
    def get(self, pdf_path):
        # 验证请求
        if not verify_request(request):
            # 如果请求不合法,返回错误信息
            return {'message': 'Invalid request'}, 401

        # 检查文件是否存在
        if not os.path.exists(pdf_path):
            return {'message': 'File not found'}, 404

        # 发送 PDF 文件
        @after_this_request
        def remove_file(response):
            # 删除临时文件
            try:
                os.remove(pdf_path)
            except Exception as e:
                app.logger.error("Error removing file: %s", str(e))
            return response

        return send_file(pdf_path), 200

# 将处理器添加到 API
api.add_resource(DocHandler, '/doc')

# 运行 Flask 应用
if __name__ == '__main__':
    app.run(port=5001, ssl_context=('cert.pem', 'key.pem'))

以上代码完成了以下任务:

  1. 初始化 Flask 应用,定义了 POST 和 GET 方法用来处理文件上传和下载。
  2. 在 POST 方法中,首先检查请求是否合法,不合法则返回 HTTP 401 Unauthorized 错误。然后检查是否上传了文件,未上传则返回 HTTP 400 Bad Request 错误。然后将上传的文件保存为 Word 文档,再将 Word 文档转换为 PDF 文件,并返回 PDF 文件的路径。
  3. 在 GET 方法中,首先检查请求是否合法,不合法则返回 HTTP 401 Unauthorized 错误。然后检查文件是否存在,不存在则返回 HTTP 404 Not Found 错误。然后发送 PDF 文件,并在发送完成后删除临时文件。

要测试 API,可以使用一下代码:

import requests
from Crypto.Hash import HMAC
from Crypto.Hash import SHA256

def send_request(url, app_key, secret_key, file_path):
    with open(file_path, 'rb') as f:
        file_data = f.read()

    # 计算 HMAC-SHA256
    h = HMAC.new(secret_key.encode('utf-8'), digestmod=SHA256)
    h.update(file_data)

    # 设置请求头
    headers = {
        'AppKey': app_key,
        'Sign': h.hexdigest(),
    }

    # 发送请求
    files = {'file': file_data}
    response = requests.post(url, headers=headers, files=files)

    return response

# 发送 Word 文件
response = send_request('https://pdf.domain.com/doc', APP_KEY, SECRET_KEY, 'path_to_your_word_file.docx')

# 获取 PDF 文件的路径
pdf_path = response.json()['pdf_path']

# 下载 PDF 文件
response = requests.get(f'https://pdf.domain.com/doc/{pdf_path}', headers={'AppKey': APP_KEY, 'Sign': SIGN})

# 保存 PDF 文件
with open('your_pdf_file.pdf', 'wb') as f:
    f.write(response.content)

以上代码首先发送 Word 文件到服务器,并获取服务器返回的 PDF 文件路径,然后下载 PDF 文件。需要注意的是,发送请求和下载文件时,都需要在请求头中添加 AppKey 和 Sign。

至于具体在明道云里怎么配置,我还没研究明白 😕