How to deploy zip files (or other binaries) trough cgi in Python? How to deploy zip files (or other binaries) trough cgi in Python? python-3.x python-3.x

How to deploy zip files (or other binaries) trough cgi in Python?


You need to print an empty line after the headers, and you Content-disposition header is missing the type (attachment):

print("Content-type: application/octet-stream")print("Content-Disposition: attachment; filename=%s.zip" %(filename))print()

You may also want to use a more efficient method of uploading the resulting file; use shutil.copyfileobj() to copy the data to sys.stdout.buffer:

from shutil import copyfileobjimport sysprint("Content-type: application/octet-stream")print("Content-Disposition: attachment; filename=%s.zip" %(filename))print()with open('../../data/code/' + filename + '.zip','rb') as zipfile:    copyfileobj(zipfile, sys.stdout.buffer)

You should not use print() for binary data in any case; all you get is b'...' byte literal syntax. The sys.stdout.buffer object is the underlying binary I/O buffer, copy binary data directly to that.


The header is malformed because, for some reason, Python sends it after sending the file.

What you need to do is flush stdout right after the header:

sys.stdout.flush()

Then put the file copy


This is what worked for me, I am running Apache2 and loading this script via cgi. Python 3 is my language.

You may have to replace first line with your python 3 bin path.

#!/usr/bin/python3import cgitbimport cgifrom zipfile import ZipFileimport sys# Files to include in archivesource_file = ["/tmp/file1.txt", "/tmp/file2.txt"]# Name and Path to our zip file.zip_name = "zipfiles.zip"zip_path = "/tmp/{}".format(zip_name)with ZipFile( zip_path,'w' ) as zipFile:    for f in source_file:        zipFile.write(f);# Closing File.zipFile.close()# Setting Proper Header.print ( 'Content-Type:application/octet-stream; name="{}"'.format(zip_name) );print ( 'Content-Disposition:attachment; filename="{}"\r\n'.format(zip_name) );# Flushing Out stdout.sys.stdout.flush()bstdout = open(sys.stdout.fileno(), 'wb', closefd=False)file = open(zip_path,'rb')bstdout.write(file.read())bstdout.flush()