简体   繁体   English

Django / reportlab:将生成的pdf直接保存到AWS s3中的FileField

[英]Django/reportlab: Save generated pdf directly to FileField in AWS s3

I am writing a Django app, for which I need to generate a PDF, using reportlab, and save it to a FileField . 我正在编写一个Django应用程序,我需要使用reportlab生成PDF,并将其保存到FileField My problem is that my media is stored in S3, and I don't know how to save this pdf directly to S3. 我的问题是我的媒体存储在S3中,我不知道如何将这个pdf直接保存到S3。

I am creating the pdf locally then reading it and saving to the FileField in s3, then deleting the local version, but I'm wondering if there's a better solution, where I can save the file directly to S3. 我在本地创建pdf然后读取并保存到s3中的FileField,然后删除本地版本,但我想知道是否有更好的解决方案,我可以将文件直接保存到S3。

here's how I generate the contract now: 这是我现在如何生成合同:

#temporary folder name to generate contract locally
folder_name = (
     '/tmp/'
     + '/contracts/'
     + gig.identifier
     )
mkdir_p(folder_name)
address = (
     folder_name
     + '/contract_'
     + lang
     + '.pdf'
 )
doc = SimpleDocTemplate(
     address,
     pagesize=A4,
     rightMargin=72,
     leftMargin=72,
     topMargin=120,
     bottomMargin=18
 )
doc.build(Story,
          canvasmaker=LogoCanvas)
local_file = open(address)
pdf_file = File(local_file)
contract = Contract.objects.create(lang=lang, gig=gig)
contract.contract_file.save('contract_'+lang+'.pdf', pdf_file)
contract.save()
#remove temporary folder
shutil.rmtree(folder_name)
return True

and the Contract model is defined like this: 合同模型定义如下:

class Contract(models.Model):
    gig = models.ForeignKey(Gig, related_name='contracts')
    lang = models.CharField(max_length=10, default='')
    contract_file = models.FileField(
        upload_to=get_contract_path,
        blank=True,
        null=True,
        default=None
    )

You can use BytesIO for creating an in-memory stream instead of a file stream. 您可以使用BytesIO创建内存中的流而不是文件流。

However, you still need to make reportlab to use that stream instead of a file. 但是,您仍需要使reportlab使用该流而不是文件。

Relying on the userguide , at 2.2 More about the Canvas , Canvas constructor has a filename parameter that can be both a string or a file descriptor. 依托userguide ,在2.2更多关于帆布 ,构造函数有一个filename参数既可以是一个字符串或文件描述符。 I have tested it with a SimpleDocTemplate , so it should work for you: 我用SimpleDocTemplate测试了它,所以它应该适合你:

import io
stream = io.BytesIO()
doc = SimpleDocTemplate(
     stream,
     pagesize=A4,
     rightMargin=72,
     leftMargin=72,
     topMargin=120,
     bottomMargin=18
 )
doc.build(Story,
          canvasmaker=LogoCanvas)
pdf_buffer = stream.getBuffer()

I don't know S3, but I'm confident that this is enough to solve your problem. 我不知道S3,但我相信这足以解决你的问题。 For instance, if you would like now to write this pdf to a file, you would do: 例如,如果您现在想将此pdf写入文件,您可以:

file = open("contract.pdf", "wb")
file.write(pdf_buffer)

You could use the standard Python module tempfile ( import tempfile ) 你可以使用标准的Python模块tempfileimport tempfile

tempfile.TemporaryFile(mode='w+b', buffering=None, encoding=None, newline=None, suffix=None, prefix=None, dir=None)

Return a file-like object that can be used as a temporary storage area. 返回一个类似文件的对象,可以用作临时存储区域。 The file is created securely, using the same rules as mkstemp(). 使用与mkstemp()相同的规则安全地创建文件。 It will be destroyed as soon as it is closed (including an implicit close when the object is garbage collected). 它将在关闭后立即销毁(包括在对象被垃圾收集时隐式关闭)。 Under Unix, the directory entry for the file is either not created at all or is removed immediately after the file is created. 在Unix下,文件的目录条目根本不是创建的,或者在创建文件后立即删除。 Other platforms do not support this; 其他平台不支持此功能; your code should not rely on a temporary file created using this function having or not having a visible name in the file system. 您的代码不应该依赖于使用此函数创建的临时文件,该文件在文件系统中具有或不具有可见名称。

https://docs.python.org/3/library/tempfile.html Your using of the tempfile object is absolutely similar to regular file. https://docs.python.org/3/library/tempfile.html使用tempfile对象与常规文件完全相似。

By the way you owe me 25$ =) 顺便你欠我25美元=)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM