如何使用Flask send_file()为pdfkit.from_string()创建的PDF文件提供服务

如何使用Flask send_file()为pdfkit.from_string()创建的PDF文件提供服务,flask,file-transfer,pdfkit,Flask,File Transfer,Pdfkit,我有一个pdfkit PDF,它可以作为Sendgrid附件正常工作,由以下函数创建: def wish_lists_pdf(user=current_user): pdf_heading = "Thank you!" pdf_subheading = "Please find the Wish Lists you signed up to sponsor listed below." pdf_context = { 'heading': pdf_hea

我有一个pdfkit PDF,它可以作为Sendgrid附件正常工作,由以下函数创建:

def wish_lists_pdf(user=current_user):
    pdf_heading = "Thank you!"
    pdf_subheading = "Please find the Wish Lists you signed up to sponsor listed below."

    pdf_context = {
        'heading': pdf_heading,
        'subheading': pdf_subheading,
        'user': user,
    }
    css = os.path.join(basedir, 'static/main.css')
    pdf_content = render_template(
        'partials/email_lists_pdf.html', **pdf_context)

    path_wkhtmltopdf = app.config['WKHTMLTOPDF_EXE']
    config = pdfkit.configuration(wkhtmltopdf=path_wkhtmltopdf)

    pdf_file = pdfkit.from_string(
        pdf_content, False, configuration=config, css=css)

    bytes_file = BytesIO(pdf_file)

    return bytes_file
实际上,sendgrid需要这一行而不是字节编码:

    encoded_file = base64.b64encode(pdf_attachment).decode()
我按照不同教程的建议尝试了这种编码和b64编码。我真的不明白编码的目的,所以这可能是我出错的原因之一。在任何情况下,我都希望为PDF文件提供一条路径:

@bp.route('download_lists_pdf/<int:user_id>', methods=['GET'])
def download_lists_pdf(user_id):
    user = User.query.filter_by(id=user_id).first()
    pdf_file = wish_lists_pdf(user=user)
    return send_file(
        pdf_file,
        as_attachment=True,
        attachment_filename="Wish List Reminder Page.pdf",
        mimetype='application/pdf',
        )
def wish_lists_pdf(user=current_user):
    pdf_heading = "Thank you!"
    pdf_subheading = "Please find the Wish Lists you signed up to sponsor listed below."

    pdf_context = {
        'heading': pdf_heading,
        'subheading': pdf_subheading,
        'user': user,
    }
    css = os.path.join(basedir, 'static/main.css')
    pdf_content = render_template(
        'partials/email_lists_pdf.html', **pdf_context)

    path_wkhtmltopdf = app.config['WKHTMLTOPDF_EXE']
    config = pdfkit.configuration(wkhtmltopdf=path_wkhtmltopdf)

    pdf_file = pdfkit.from_string(
        pdf_content, False, configuration=config, css=css)

    return pdf_file
提前感谢您的帮助

编辑:在下面进行了尝试,但无效

    bytes_file = BytesIO(pdf_file)

    return bytes(bytes_file), 200, {
        'Content-Type': 'application/pdf',
        'Content-Disposition': 'inline; filename="Wish List reminder sheet.pdf"'}

如果PDF文件为
字节\u文件

return bytes(byte_file), 200, {
    'Content-Type': 'application/pdf',
    'Content-Disposition': 'inline; filename="nameofyourchoice.pdf"'}

应该可以。我找到了解决办法。它使用直接从pdfkit返回的PDF文件,然后使用Flask响应提供该文件

以下是返回PDF文件的函数:

@bp.route('download_lists_pdf/<int:user_id>', methods=['GET'])
def download_lists_pdf(user_id):
    user = User.query.filter_by(id=user_id).first()
    pdf_file = wish_lists_pdf(user=user)
    return send_file(
        pdf_file,
        as_attachment=True,
        attachment_filename="Wish List Reminder Page.pdf",
        mimetype='application/pdf',
        )
def wish_lists_pdf(user=current_user):
    pdf_heading = "Thank you!"
    pdf_subheading = "Please find the Wish Lists you signed up to sponsor listed below."

    pdf_context = {
        'heading': pdf_heading,
        'subheading': pdf_subheading,
        'user': user,
    }
    css = os.path.join(basedir, 'static/main.css')
    pdf_content = render_template(
        'partials/email_lists_pdf.html', **pdf_context)

    path_wkhtmltopdf = app.config['WKHTMLTOPDF_EXE']
    config = pdfkit.configuration(wkhtmltopdf=path_wkhtmltopdf)

    pdf_file = pdfkit.from_string(
        pdf_content, False, configuration=config, css=css)

    return pdf_file
以下是观点:

@bp.route('download_lists_pdf/<int:user_id>', methods=['GET'])
def download_lists_pdf(user_id):
    user = User.query.filter_by(id=user_id).first()
    pdf_file = wish_lists_pdf(user=user)

    response = Response(pdf_file)
    response.headers['Content-Disposition'] = "inline; 'Wish List reminder page'"
    response.mimetype = 'application/pdf'
    return response
@bp.route('download_lists_pdf/',methods=['GET']))
def下载列表pdf(用户id):
user=user.query.filter\u by(id=user\u id).first()
pdf文件=愿望列表\U pdf(用户=用户)
响应=响应(pdf_文件)
response.headers['Content-Disposition']=“inline;'愿望列表提醒页面'”
response.mimetype='application/pdf'
返回响应

我认为如果它能在一个新的标签中打开,或者下载时不在浏览器中打开会更理想,但这就足够了。

如果你想返回PDF文件作为响应,那么你可以试试这个-

pdf = BytesIO(pdf_attachment)
response = pdf.getvalue()
pdf.close()
return response, 200, {
        'Content-Type': 'application/pdf',
        'Content-Disposition': 'inline; filename="name_of_file.pdf"'} 

嘿,谢谢你的回复。我试过了,它给了我这个错误:TypeError:view函数没有返回有效的响应。返回类型必须是字符串、dict、tuple、响应实例或WSGI可调用,但它是BytesIO。请尝试
bytes(byte\u文件)
。我从中提取的代码已经这样做了。我修正了上面的答案。嗯,上面的编辑是你的意思吗?我试过了,得到了TypeError:“bytes”对象不能解释为整数这对我来说很好,谢谢Dave