如何将 html 字符串作为 pdf 文件上传到 Google 云存储? (Python)

How to upload an html string as pdf file to Google Cloud Storage ? (Python)

我正在尝试将 HTML 字符串作为 PDF 文件从我的 Django 应用程序上传到 GCS。

import google, os
from google.cloud import storage


class GcpHelper:
    def __init__(self, bucket_name):
        self.service_account_json_path = 'google_auth.json'
        storage_client = storage.Client.from_service_account_json(self.service_account_json_path)
        try:
            self.__bucket_name = bucket_name
            self.bucket = storage_client.get_bucket(bucket_name)
        except Exception as err:
            logger.error("Error {} while connecting to bucket {}!".format(str(err), bucket_name))


    def put_data_in_bucket(self, file_name, data, content_type="application/pdf"):
        """Uploads data to gcp bucket"""
        try:
            blob = self.bucket.blob(file_name)
            blob.upload_from_string(data, content_type=content_type)
            return True
        except Exception as err:
            logger.error("Unable to upload file {} due to {}".format(file_name, str(err)))
            raise Exception("Write to gcp failed!")


gcp_helper = GcpHelper('bucket_name')
voucher_html = open('voucher_test.html').read()
#some operations on voucher_html string here
gcp_helper.put_data_in_bucket("booking/voucher.pdf", voucher_html)

我试图以某种方式直接上传字符串,而不是将其保存为 PDF 文件然后再上传文件。 (如果没有任何效果,则必须这样做)

但是当然这不起作用,因为上传的 PDF 文件已损坏。我希望 blob.upload_from_string 会处理任何看起来 required.But 的 formatting/encoding,但事实并非如此。 ;)

您可以使用临时文件将您的 PDF 写入磁盘,然后将文件上传到云存储

import os
from tempfile import NamedTemporaryFile


with NamedTemporaryFile(mode='w+b') as temp:
    #data msut be the file that came from the request
    temp.write(data)
    temp.close()
    with open(temp.name, 'rb') as pdf:
        blob.upload_from_file(pdf)

GCS 永远不会将您的 HTML 转换为 PDF 文件

将 HTML 转换为 PDF 始终是一项艰巨的任务,但无法使用 Cloud Storage 自动执行此操作。

要使用 pdfkit 并避免任何格式问题,我建议:

  • 使用纯HTML5+CSS,减少JS的使用
  • 使用图像代替 JS 图形
  • 只使用原生 JS
  • 加载图像的最快方法是将图像加载为 base64 字符串

在过去的项目中使用了这个策略:

  • 用phantom制作我的图片,因为我有很多漂亮的 图表但使用 JS
  • 在后端创建一个 HTML 文件,其中包含所有信息和 使用 base 64
  • 嵌入的图像
  • 我用 celery 创建了一个任务队列,pdf 创建花了我 30 秒 因为每份报告有 500 - 1K 页

我在这个 github file

中找到了类似的方法
def to_pdf(self):
        template = get_template('{template}/{template}.html'.format(template=self.html_template))
        invoice = template.render({
            'site': Site.objects.get_current(),
            'invoice': self,
            'users': (
                ('provider', self.provider),
                ('client', self.client),
            ),
            'line_items': self.aggregate_line_items(),
            'currency': self.hourly_rate.hourly_rate_currency
        })
        self.pdf_path = os.path.join(settings.INVOICE_PDF_PATH, '{}.pdf'.format(uuid.uuid4()))
        pdf_configuration = pdfkit.configuration(wkhtmltopdf=settings.HTML_TO_PDF_BINARY_PATH)
        pdfkit.from_string(invoice, self.pdf_path, configuration=pdf_configuration, options=self.PDF_OPTIONS)
        return self.pdf_path