Flask - PyPDF2 - Exporting in memory pdf file - flask

I'm trying to export a pdf file from a flask app but for some reason I can't seem to write it correctly.
It does work when I'm exporting to my local folder but I get a blank pdf when exporting through Flask.
Any ideas ?
pdf = PdfFileWriter()
p1 = PdfFileReader(open(os.path.join(STATICDIR,'page1.pdf'), "rb"))
p2 = PdfFileReader(open(os.path.join(STATICDIR,'page2.pdf'), "rb"))
p3 = PdfFileReader(open(os.path.join(STATICDIR,'lastpage.pdf'), "rb"))
pdf.addPage(p1.getPage(0))
pdf.addPage(p2.getPage(0))
pdf.addPage(p3.getPage(0))
#this works
#outputStream = open(r"output.pdf", "wb")
#pdf.write(outputStream)
outfile = BytesIO()
pdf.write(outfile)
return Response(pdf, mimetype='application/pdf',
headers={'Content-Disposition': 'attachment;filename=output.pdf'})

BytesIO is just a buffer containing some data it isn't associated with any real file on the disk, It's just a chunk of memory that behaves like a file. You first need to write the contents of PdfFileWriter() to the buffer then write the values of the buffer to the pdf file. Flask has a neat function send_file which allows you to send the contents of a file to the client.
from pypdf2 import PdfFileWriter
from flask import send_file
pdf = PdfFileWriter()
p1 = PdfFileReader(open(os.path.join(STATICDIR,'page1.pdf'), "rb"))
p2 = PdfFileReader(open(os.path.join(STATICDIR,'page2.pdf'), "rb"))
p3 = PdfFileReader(open(os.path.join(STATICDIR,'lastpage.pdf'), "rb"))
pdf.addPage(p1.getPage(0))
pdf.addPage(p2.getPage(0))
pdf.addPage(p3.getPage(0))
#this works
outputStream = open(r"output.pdf", "wb")
pdf.write(outputStream)
outfile = BytesIO()
pdf.write(outfile)
with open("output.pdf", "wb") as f:
f.write(outfile.getvalue())
return send_file('./output.pdf', mimetype='application/pdf')

Here is the clean code thanks to #darth baba.
I've also added a pptx export that works with this method :
#
#1. PDF EXPORT
#
from pypdf2 import PdfFileWriter
from flask import send_file
pdf = PdfFileWriter()
p1 = PdfFileReader(open(os.path.join(STATICDIR,'page1.pdf'), "rb"))
p2 = PdfFileReader(open(os.path.join(STATICDIR,'page2.pdf'), "rb"))
p3 = PdfFileReader(open(os.path.join(STATICDIR,'lastpage.pdf'), "rb"))
pdf.addPage(p1.getPage(0))
pdf.addPage(p2.getPage(0))
pdf.addPage(p3.getPage(0))
#this works
outputStream = open(r"output.pdf", "wb")
pdf.write(outputStream)
outfile = BytesIO()
pdf.write(outfile)
outfile.seek(0)
return send_file(outfile,
mimetype='application/pdf'
attachment_filename='output.pptx')
#
#2. PPTX EXPORT
#
from pptx import Presentation
from flask import send_file
prs = gen.GenPPT(STATICDIR, lst_ath, lst_choice_sous_cat) #creates presentation
outfile = BytesIO()
prs.save(outfile)
outfile.seek(0)
return send_file(outfile,
mimetype="application/vnd.openxmlformats-officedocument.presentationml.presentation",
as_attachment=True,
attachment_filename='output.pptx')

Related

django export xls as zip doesn't work: format unknown

I want to make a view that produce xls file using xlwt and make file downloaded as zip file using zipfile.
def export(request):
filename = "myfile.xls"
wb = xlwt.Workbook(encoding='utf-8')
....
buffer1 = io.BytesIO()
wb.save(buffer1)
buffer2 = io.BytesIO()
with zipfile.ZipFile(buffer2, mode='w') as zip_file:
zip_file.writestr(zinfo_or_arcname=filename, data=buffer1.getvalue())
response = HttpResponse(content_type='application/x-zip-compressed')
response['Content-Disposition'] = 'attachment; filename=myzip.zip'
return response
but when I try to unzip I got an error: file format unknown

Sending an Excel file from postoffice

I am trying to send a base64-encoded excel file through Django post_office lib. Here's the code that I have now
An example of encoded content:
body = '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'
The body above is the result of the following code:
import base64
f = open(file_path, 'rb')
file_content = f.read()
return base64.b64encode(file_content).decode('UTF-8')
The the code itself:
from django.core.files.base import ContentFile
from post_office import mail
attachments = [{
'name': 'example.xlsx',
'body': ContentFile(body),
'mimetype': 'application/vnd.ms-excel'}]
mail.send(to, from, attachments=attachments, **params)
The problem is that the content in the actual file that is sent by email looks like this:
What could be the reason for that ?
ContentFile has no clue that the content you're passing it is base 64 encoded. You need to base-64-decode it first to pass the actual raw bytes of the Excel file to it.

django PDF FileResponse "Failed to load PDF document."

I am trying to generate and output PDF from a django view. I followed the example in django documentation using ReportLab but the downloaded PDF is not opening in any PDF readers.
I use Python 3.7.0, Django==2.1.3, reportlab==3.5.12. I tried adding content_type="application/pdf" to 'FileResponse` but still having the same issue.
import io
from django.http import FileResponse
from reportlab.pdfgen import canvas
def printPDF(request):
# Create a file-like buffer to receive PDF data.
buffer = io.BytesIO()
# Create the PDF object, using the buffer as its "file."
p = canvas.Canvas(buffer)
p.drawString(100, 100, "Hello world.")
p.showPage()
p.save()
return FileResponse(buffer, as_attachment=True, filename='hello.pdf')
The generated PDF should be opening in all PDF readers. But I am getting 'Failed to load PDF document.'
buffer = BytesIO() is used instead of a file to store the pdf document. Before returning it with FileResponse you need to reset the stream position to its start:
buffer.seek(io.SEEK_SET)
Now the pdf download should work as expected.
There seems to be something fishy going on with the interaction of BytesIO and FileResponse. The following worked for me.
def printPDF(request):
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename=hello.pdf'
p = canvas.Canvas(response)
p.drawString(100, 100, "Hello world.")
p.showPage()
p.save()
return response

download images through django

I try to download an image from my django website. I do it like this:
def file_download(request, filename):
from django.core.servers.basehttp import FileWrapper
import mimetypes
import settings
import os
filepath = os.path.join(settings.MEDIA_ROOT, filename)
wrapper = FileWrapper(open(filepath))
content_type = mimetypes.guess_type(filepath)[0]
response = HttpResponse(wrapper, mimetype='content_type')
response['Content-Disposition'] = "attachment; filename=%s" % filename
return response
However, it doesn't work for images (I tries jpg files), but do work for txt files. Why?
Probably you need to open the file in binary mode:
wrapper = FileWrapper(open(filepath, 'rb'))

Django with mod_XSENDFILE unable to download complete file

Attached is the code which downloads a file from browser using django 1.3 and Apache 2.2 with mod_xsendfile
#login_required
def sendfile(request, productid):
path = settings.RESOURCES_DIR
filepath = os.path.join('C:/workspace/y/src/y/media/audio/','sleep_away.mp3')
print "filepath",filepath
filename = 'sleep_away.mp3' # Select your file here.
print "Within sendfile size", os.path.getsize(filepath)
wrapper = FileWrapper(open(filepath,'r'))
content_type = mimetypes.guess_type(filename)[0]
response = HttpResponse(wrapper, content_type = content_type)
print "Within wrapper"
from django.utils.encoding import smart_str
response['X-Sendfile'] = smart_str(filepath)
response['Content-Length'] = os.path.getsize(filepath)
from django.utils.encoding import smart_str
response['Content-Disposition'] = 'attachment; filename=%s/' % smart_str(filename)
return response
The console shows the following filesize which is the right size
Within sendfile size 4842585
But when I download/save the file it shows 107 KB...i.e 109,787 bytes.Where am I going wrong. Why isnt it downloading the complete file?
I consider your new to django or python. Try to put the import statements at the beginning of the method. Once imported it can be used through the method no need import every time you use. In windows you should use "rb" (read binary) to serve anything other than text files. Try not to use variable names that might conflict with method names or other keywords of the language. Your method should be like this
#login_required
def sendfile(request, productid):
from django.utils.encoding import smart_str
##set path and filename
resource_path = settings.RESOURCES_DIR # resource dir ie /workspace/y/src/y/media
filename = "sleep_away.mp3" #file to be served
##add it to os.path
filepath = os.path.join(resource_path,"audio",filename)
print "complete file path: ", filepath
##filewrapper to server in size of 8kb each until whole file is served
file_wrapper = FileWrapper(file(filepath,'rb')) ##windows needs rb (read binary) for non text files
##get file mimetype
file_mimetype = mimetypes.guess_type(filepath)
##create response with file_mimetype and file_wrapper
response = HttpResponse(content_type=file_mimetype, file_wrapper)
##set X-sendfile header with filepath
response['X-Sendfile'] = filepath ##no need for smart_str here.
##get filesize
print "sendfile size", os.stat(filepath).st_size
response['Content-Length'] = os.stat(filepath).st_size ##set content length
response['Content-Disposition'] = 'attachment; filename=%s/' % smart_str(filename) ##set disposition
return response ## all done, hurray!! return response :)
Hope that helps
You could have a look at the django-private-files project. Haven't tested it myself, but it looks promissing.
link to the docs --> http://readthedocs.org/docs/django-private-files/en/latest/usage.html
cheers