2017-04-12 35 views
1

我正在编写一个Django应用程序,为此需要使用reportlab生成PDF,并将其保存到FileField。我的问题是我的媒体存储在S3中,我不知道如何将此pdf直接保存到S3。Django/reportlab:将生成的pdf直接保存到AWS的FileField中s3

我在本地创建pdf,然后读取它并保存到s3中的FileField,然后删除本地版本,但我想知道是否有更好的解决方案,我可以将文件直接保存到S3。

这里就是我产生现在的合同:这样定义

#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 

和合同模式:

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 
    ) 

回答

0

可以使用BytesIO创建一个内存流,而不是一个文件流。

但是,您仍然需要使reportlab使用该流而不是文件。

依托userguide,在2.2更多关于帆布,帆布构造具有filename参数既可以是一个字符串或文件描述符。我有一个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() 

我不知道S3,但我相信,这是足以解决你的问题。例如,如果您现在想要将此pdf写入文件,您应该这样做:

file = open("contract.pdf", "wb") 
file.write(pdf_buffer) 
相关问题