使用 Flask 和 pdfkit 生成带透明 PNG 盖章的 PDF 并上传到阿里云 OSS

在现代 Web 开发中,生成 PDF 文档并在其上添加盖章是常见的需求。本文将详细介绍如何使用 Flask 框架和 pdfkit 库来批量生成 PDF,并在其中添加透明 PNG 盖章,最后将生成的 PDF 上传到阿里云 OSS(对象存储服务)。

环境准备

首先,确保您的开发环境中已安装以下依赖:

bash 复制代码
pip install Flask pdfkit Pillow PyPDF2 aliyun-oss2

此外,您还需要安装 wkhtmltopdf,这是 pdfkit 的依赖。根据您的操作系统选择安装方式:

  • Ubuntu:

    bash 复制代码
    sudo apt-get install wkhtmltopdf
  • CentOS:

    bash 复制代码
    sudo yum install wkhtmltopdf

项目结构

以下是 Flask 应用的基本结构:

复制代码
/your_project
│
├── app.py               # 主应用文件
├── uploads              # 存放生成的 PDF 文件
└── stamp.png            # 透明 PNG 盖章文件

确保将您的透明 PNG 盖章文件放在项目目录中。

Flask 应用代码

以下是完整的 Flask 应用代码,包含生成 PDF、添加盖章以及上传到 OSS 的功能:

python 复制代码
from flask import Flask, request, jsonify, send_file
import pdfkit
import os
from PIL import Image
from werkzeug.utils import secure_filename
import oss2

app = Flask(__name__)

# 设置上传文件的目录
UPLOAD_FOLDER = 'uploads'
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

# OSS 配置
OSS_ACCESS_KEY_ID = 'your_access_key_id'
OSS_ACCESS_KEY_SECRET = 'your_access_key_secret'
OSS_ENDPOINT = 'your_oss_endpoint'  # 例如 'oss-cn-region.aliyuncs.com'
OSS_BUCKET_NAME = 'your_bucket_name'

# 初始化 OSS 客户端
auth = oss2.Auth(OSS_ACCESS_KEY_ID, OSS_ACCESS_KEY_SECRET)
bucket = oss2.Bucket(auth, OSS_ENDPOINT, OSS_BUCKET_NAME)

# PDF 生成函数
def create_pdf(html_content, output_path):
    pdfkit.from_string(html_content, output_path)

# 加盖章函数
def add_stamp_to_pdf(pdf_path, stamp_path, output_path):
    from PyPDF2 import PdfWriter, PdfReader

    stamp = Image.open(stamp_path)
    stamp.save('temp_stamp.pdf', "PDF")

    with open(pdf_path, "rb") as pdf_file, open('temp_stamp.pdf', "rb") as stamp_file:
        pdf_reader = PdfReader(pdf_file)
        stamp_reader = PdfReader(stamp_file)
        writer = PdfWriter()

        for page in pdf_reader.pages:
            page.merge_page(stamp_reader.pages[0])
            writer.add_page(page)

        with open(output_path, "wb") as output_file:
            writer.write(output_file)

# 上传文件到 OSS
def upload_to_oss(file_path, object_name):
    bucket.put_object_from_file(object_name, file_path)

@app.route('/generate_pdf', methods=['POST'])
def generate_pdf():
    data = request.get_json()
    if not data or 'html_content' not in data:
        return jsonify({"error": "Invalid input"}), 400

    html_content = data['html_content']
    stamp_path = data.get('stamp_path')  # 可选盖章路径
    filename = secure_filename('output.pdf')
    output_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)

    try:
        create_pdf(html_content, output_path)
        if stamp_path:
            output_path_with_stamp = os.path.join(app.config['UPLOAD_FOLDER'], 'stamped_' + filename)
            add_stamp_to_pdf(output_path, stamp_path, output_path_with_stamp)
            # 上传到 OSS
            upload_to_oss(output_path_with_stamp, 'pdfs/' + filename)
            return send_file(output_path_with_stamp, as_attachment=True)
        # 上传到 OSS
        upload_to_oss(output_path, 'pdfs/' + filename)
        return send_file(output_path, as_attachment=True)
    except Exception as e:
        return jsonify({"error": str(e)}), 500

@app.route('/batch_generate', methods=['POST'])
def batch_generate():
    data = request.get_json()
    if not data or 'html_contents' not in data:
        return jsonify({"error": "Invalid input"}), 400

    output_files = []
    stamp_path = data.get('stamp_path')  # 可选盖章路径
    for index, html_content in enumerate(data['html_contents']):
        filename = secure_filename(f'output_{index}.pdf')
        output_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        
        try:
            create_pdf(html_content, output_path)
            if stamp_path:
                output_path_with_stamp = os.path.join(app.config['UPLOAD_FOLDER'], 'stamped_' + filename)
                add_stamp_to_pdf(output_path, stamp_path, output_path_with_stamp)
                # 上传到 OSS
                upload_to_oss(output_path_with_stamp, 'pdfs/' + filename)
                output_files.append(output_path_with_stamp)
            else:
                # 上传到 OSS
                upload_to_oss(output_path, 'pdfs/' + filename)
                output_files.append(output_path)
        except Exception as e:
            return jsonify({"error": f"Failed to generate PDF {index}: {str(e)}"}), 500

    return jsonify({"message": "PDFs generated and uploaded to OSS", "files": output_files}), 200

if __name__ == '__main__':
    app.run(debug=True)

代码解析

1. 环境设置

在代码中设置了上传文件的目录,并确保该目录存在。

2. OSS 配置

配置阿里云 OSS 的访问密钥和存储桶信息,并初始化 OSS 客户端。

3. PDF 生成函数

使用 pdfkit 从 HTML 内容生成 PDF 文件。

4. 加盖章函数

使用 Pillow 加载透明 PNG 盖章,并使用 PyPDF2 将其添加到生成的 PDF 上。

5. 上传文件到 OSS

创建 upload_to_oss 函数,将生成的 PDF 文件上传到阿里云 OSS。

6. API 端点

  • /generate_pdf:接收单个 HTML 内容和可选的盖章 PNG 路径,生成 PDF 并上传到 OSS。
  • /batch_generate:接收多个 HTML 内容和可选的盖章 PNG 路径,批量生成 PDF 并上传到 OSS。

使用示例

生成单个 PDF

/generate_pdf 发送 POST 请求,包含 HTML 内容和可选的 PNG 图片路径:

json 复制代码
{
    "html_content": "<h1>Hello, World!</h1>",
    "stamp_path": "path/to/stamp.png"
}

批量生成 PDF

/batch_generate 发送 POST 请求,包含多个 HTML 内容和可选的 PNG 图片路径:

json 复制代码
{
    "html_contents": [
        "<h1>Document 1</h1>",
        "<h1>Document 2</h1>"
    ],
    "stamp_path": "path/to/stamp.png"
}

注意事项

  • 安全性:妥善管理您的 OSS 密钥信息,避免在公共代码中暴露。
  • OSS 权限:确保您的阿里云 OSS 存储桶具有相应的权限,以允许上传和访问文件。

总结

通过使用 Flask、pdfkit、透明 PNG 图片和阿里云 OSS,您可以轻松地生成带有盖章的 PDF 文档,并将其上传到云端存储。这种方法在处理大量文档时特别有用,可以有效提高工作效率。

相关推荐
TMT星球3 小时前
中国AI云市场报告:阿里云份额达35.8%,高于2至4名总和
人工智能·阿里云·云计算
Evan Wang6 小时前
使用Terraform管理阿里云基础设施
阿里云·云原生·terraform
拓端研究室6 小时前
专题:2025人形机器人、工业机器人、智能焊接机器人、扫地机器人产业洞察报告 | 附158+份报告PDF、数据仪表盘汇总下载
microsoft·机器人·pdf
TextIn智能文档云平台7 小时前
复杂PDF文档结构化提取全攻略——从OCR到大模型知识库构建
pdf·ocr
会飞的小菠菜7 小时前
PDF文件中的广告二维码图片该怎么批量删除
pdf·删除·二维码·批量
衍余未了8 小时前
k8s 内置的containerd配置阿里云个人镜像地址及认证
java·阿里云·kubernetes
一只花里胡哨的程序猿1 天前
odoo打印pdf速度慢问题
pdf·odoo
灵海之森1 天前
Python将md转html,转pdf
pdf
阿幸软件杂货间1 天前
最新PDF版本!Acrobat Pro DC 2025,解压即用版
pdf·adobe acrobat·acrobat
星空的资源小屋1 天前
网易UU远程,免费电脑远程控制软件
人工智能·python·pdf·电脑