使用 python 脚本创建 pdf 文件

Creating a pdf file with a python script

我正在尝试制作一个 python 脚本,它将在每天午夜使用 cron 生成一个 pdf 文件。 cron 部分工作正常。问题是,当我执行 python 脚本时,pdf 文件没有存储在我希望存储的位置。我从 render_template 函数收到正确的消息(加载页面 (1/2) 打印页面 (2/2) 完成),但 pdf 文件不存在。任何帮助将不胜感激!

这是我的 python 代码:

import os, subprocess, re, datetime
from conf import config
import datetime
from flask import Flask, render_template, make_response
import pdfkit

app = Flask(__name__, template_folder='templates')
app.debug=True

@app.route('/')
def main():
    cur_date = datetime.datetime.now()
    cur_year = cur_date.year
    cur_month = cur_date.month
    cur_day = cur_date.day
    date_str = str(cur_year) + "/" + str(cur_month) + "/" + str(cur_day)
    with app.app_context():
        x = render_template("daily_update.htm")
        pdf = pdfkit.from_string(x, False)
        response = make_response(pdf)
        response.headers["Content-Type"] = "application/pdf"
        response.headers["Content-Disposition"] = "inline; filename=output.pdf"
        return (response)

if __name__ == "__main__":
    main()

I would like to just be able to launch this script once every 24 hours thanks to cron so that my clients have the daily pdf stored in their system but maybe I'm not doing this the right way

我认为问题在于您将其构建为经典 Flask 应用程序,因为您需要使用 render_template 函数;但实际上不需要 @app.route 装饰器提供的端点,也不需要 web-friendly 响应 Content-Disposition headers 等

一个更简单的方法可能是:

import os, subprocess, re, datetime
import datetime
from flask import Flask, render_template
import pdfkit

def make_pdf(filename, template_folder):

    # Define the app here (explained later)
    app = Flask(__name__, template_folder=template_folder)

    cur_date = datetime.datetime.now()
    cur_year = cur_date.year
    cur_month = cur_date.month
    cur_day = cur_date.day
    date_str = str(cur_year) + "/" + str(cur_month) + "/" + str(cur_day)

    with app.app_context():
        x = render_template("daily_update.htm", DATE=date_str)

    print(x) # `x` is now the string you want to write to the PDF

    # `pdfkit.from_string` has native ability to write to a file:
    pdf = pdfkit.from_string(x, filename)
        
if __name__ == "__main__":
    make_pdf('output.pdf','templates')

我在 templates/daily_update.htm 模拟了一个示例模板,内容为:

Sample template, the date is {{DATE}}

这会生成一个名为 output.pdf 的 PDF,其内容为:

Sample template, the date is 2021/8/30

另请注意,通过在 make_pdf 函数中定义 app 变量,您可以在调用函数时指定 template_folder

所以你可以做一些聪明的事情,如果你想为每个客户创建一个模板文件夹,用于他们自己的自定义模板,然后调用类似的东西:

if __name__ == "__main__":
    make_pdf('special_customer_report.pdf', 'special_customer_templates')

更新:

I have no idea how I could save these pdfs on the client's side basicaly

如果您实际将此应用程序部署到客户端计算机,这将起作用。如果您正在集中思考或 运行 这个问题,并以某种方式将 PDF 发送到客户的机器上,那么那里有很多变量/设计决策,这有点超出了这个问题的上下文。