Reputation: 1015
Let me break down my requirement. Here's what I'm doing right now.
1. Generate PDF files from HTML
for this I'm using Weasyprint as following:
lstFileNames = []
for i, content in enumerate(lstHtmlContent):
repName = 'report'+ str(uuid.uuid4()) + '.pdf'
lstFileNames.append("D:/Python/Workspace/" + repName)
HTML(string=content).write_pdf(target=repName,
stylesheets=[CSS(filename='/css/bootstrap.css')])
all files names, with paths, are saved in lstFileNames
.
2. Create a zip file with pdf files generated by weasyprint
for this I'm using zipfile
zipPath = 'reportDir' + str(uuid.uuid4()) + '.zip'
myzip = zipfile.ZipFile(zipPath, 'w')
with myzip:
for f in lstFileNames:
myzip.write(f)
3. Send zip file to client for download
resp = HttpResponse(myzip, content_type = "application/x-zip-compressed")
resp['Content-Disposition'] = 'attachment; filename=%s' % 'myzip.zip'
4. Open file for downloading via Javascript
var file = new Blob([response], {type: 'application/x-zip-compressed'});
var fileURL = URL.createObjectURL(file);
window.open(fileURL);
Problems
1. While the zip file is successfully received at front end, after I try to open it, it gives the following error:
The archive is in either unknown format or damaged
Am I sending the file wrong or is my Javascript code the problem?
2. Is there a way to store all pdf files in list of byte arrays and generate zip files with those byte array and send it to the client? I tried that with weasyprint but the result was same damaged file
.
3. Not exactly a problem but I haven't been able to find it in weasyprint docs. Can I enforce the path to where the file should be saved?
Problem # 1 is of extreme priority, rest are secondary. I would like to know if I'm doing it right i.e. generating pdf files and sending their zip file to client.
Thanks in advance.
Upvotes: 0
Views: 2513
Reputation: 4968
A slightly different approach would be to move the zip file to a public directory and then send that location to the client (e.g. json formatted), i.e.:
publicPath = os.path.join('public/', os.path.basename(zipPath))
os.rename(zipPath, os.path.join('/var/www/', publicPath))
jsonResp = '{ "zip-location": "' + publicPath + '" }'
resp = HttpResponse(jsonResp, content_type = 'application/json');
Then in your client's javascript:
var res = JSON.parse(response);
var zipFileUrl = '/' + res['zip-location'];
window.open(zipFileUrl, '_blank');
'/' + res['zip-location']
assumes that your page lives in the same folder as the public
directory (so http://example.com/public/pdf-files-123.zip
points to /var/www/public/pdf-files-123.zip
on your file system).
You can clean up the public
directory with a cron job that deletes all the .zip
files in there that are older than an hour or so.
Upvotes: 1
Reputation: 308909
Once you have exited the with
block the filehandle is closed. You should reopen the file (this time with open) and use read()
to pass the contents to HttpResponse
instead of passing the filehandle itself.
with zipfile.ZipFile(zipPath, 'w') as myzip
for f in lstFileNames:
myzip.write(f)
with open(zipPath, 'r') as myzip:
return HttpResponse(myzip.read(), content_type = "application/x-zip-compressed")
If that works, then you can use a StringIO
instance instead of a filehandle to store the zip file. I'm not familiar with Weasyprint so I don't know whether you can use StringIO
for that.
Upvotes: 0