I would like to create a zip file on the fly to serve to users through Cherry Py: I tried the following code that produced an invalid zip file:
#cherrypy.expose
def ZipDir(self, *args):
path = "\\".join(args)
output = StringIO.StringIO()
file = zipfile.ZipFile(output, "w")
zip_filename = path + ".zip"
cherrypy.response.headers['Content-Type'] = 'application/zip'
cherrypy.response.headers['Content-Disposition'] = 'attachment; filename="%s"' % (zip_filename,)
dir = filter(lambda x: x.lower().endswith(".mp3") or not ("." in x), os.listdir("G:\\Music\\" + path))
for f in dir:
file.write("G:\\Music\\" + path + "\\" + f,f,zipfile.ZIP_DEFLATED)
return output.getvalue()
The file size looks about right, but it doesnt register as a zip file with any acrhicing applications.
I forgot to call file.close() before the return. That fixed it!
Related
I am currently trying to create a function within a Django app to download a pandas dataframe as an image. I wanted to create the image as a temporary file, download it, then delete it. Does anyone know how to integrate tempfile into this code?
Views.py
def download_png(request, study):
Names(study) #Funciton to get (name) variable
Retrieve(study) #Function to get (data) variable
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
pngfilename = str(name) + "_" + str(current_time) + ".png"
temp = tempfile.NamedTemporaryFile(suffix=".png")
fig = temp.write(df2img.plot_dataframe(data))
filepath = temp.name
response = HttpResponse(df2img.save_dataframe(fig=fig, filename=filepath), content_type=mimetypes.guess_type(filepath))
response['Content-Disposition'] = "attachment; filename=%s" % pngfilename
return response
Update 06/30/22:
I had a lot of difficulty integrating the tempfile module because it requires data to be converted to bytes-like objects. Instead I simply resolved on deleting the file after creating it.
def download_png(request, study):
Names(study)
Retrieve(study)
pngfilename = str(name) + "_" + str(current_time) + ".png"
mime_type, _ = mimetypes.guess_type(pngfilename)
fig = df2img.plot_dataframe(data)
df2img.save_dataframe(fig=fig, filename=pngfilename)
response = FileResponse(open(pngfilename, 'rb'), content_type=mime_type)
response['Content-Disposition'] = "attachment; filename=%s" % pngfilename
os.remove(pngfilename)
return response
This is how you can use the tempfile library:
tempfile = tempfile.mktemp(suffix='.png')
with open(temp, 'w') as f:
f.write(df2img.plot_dataframe(data))
do_something_with_your_file(temp)
os.unlink(temp)
Edit: was just reading the tempfile documentation and apparently tempfile.mktemp is prone to race conditions, so you should either use tempfile.mkstemp like:
fd, tempf = tempfile.mkstemp()
Or there is a context manager:
with tempfile.NamedTemporaryFile() as tmp:
with open(tmp.name, 'w') as f:
f.write('some data')
# do something with your tempfile file
And then it will automatically delete the tempfile afterwards.
I'm going to create a zip file from some of the image files stored on my server.
I've used the following function to do this:
def create_zip_file(user, examination):
from lms.models import StudentAnswer
f = BytesIO()
zip = zipfile.ZipFile(f, 'w')
this_student_answer = StudentAnswer.objects.filter(student_id=user.id, exam=examination)
for answer in this_student_answer:
if answer.answer_file:
answer_file_full_path = answer.answer_file.path
fdir, fname = os.path.split(answer_file_full_path)
zip.writestr(fname, answer_file_full_path)
zip.close() # Close
zip_file_name = "student-answers_"+ str(examination.id)+"_" + str(user.id) + "_" + date=datetime.datetime.now().strftime("%Y-%m-%d-%H-%M") + '.zip'
response = HttpResponse(f.getvalue(), content_type="application/x-zip-compressed")
response['Content-Disposition'] = 'attachment; filename=%s' % zip_file_name
return response
Everything is fine and all photos are made in zip file but there is only one problem.
The problem is that the photos won't open and this error will appear in Windows:
Its look like we don't support this file format.
What is wrong with my codes?
To append data from file you have to use
write(filename)
Using writestr(filename) you add only string from variable filename but not from file.
My requirement is
File upload,
Rename the file,
Compress it - make it as a zip,
Save in required location,
unzip the zip file,
Remove the zip file,
save the renamed file and filesize in DB
Renaming and zipping the file is not happening. Let me add my code here
#app.route('/temp/upload', methods=['POST'])
def upload():
if request.method == 'POST':
f = request.files['file']
random_string = generate_random(5)
print "Random string=> ", random_string # wqzhp
print "f.filename->>> ", f.filename # form3.pdf
fn = f.filename
fname = (fn).split(".")
random_file_name = fname[0] + '-' + random_string + "." + fname[1]
print "random_file_name>> ", random_file_name # form3-wqzhp.pdf
actual_file = os.path.join(load_path, random_file_name)
print "Actual file -> ", actual_file # uploadedDocs/1/form3-wqzhp.pdf
zip_f_name = actual_file + ".zip"
print "zip_f_name--> ", zip_f_name # uploadedDocs/1/form3-wqzhp.pdf.zip
f.save(zip_f_name)
zip_ref = zipfile.ZipFile(zip_f_name, 'r')
zip_ref.extractall(load_path)
zip_ref.close()
os.remove(zip_f_name)
if update_file_status(random_file_name, 0, csvid) is False:
return "update failed"
return "success"
When the zip is extracted, only original file uploaded is unzipped. zipping with the renamed file is not happening! How to save the renamed file in zip?
Any Clues!
I am currently using the code below to generate a word document and then serve this on the web using cherrypy.
tpl.get_docx().save(iostream)
cherrypy.response.headers['Content-Type'] = (
'application/vnd.openxmlformats-officedocument'
'.wordprocessingml.document'
)
cherrypy.response.headers['Content-Disposition'] = (
'attachment; filename={fname}.docx'.format(
fname='SP' + kwargs['sp'] + '-'+ kwargs['WO'] + ' ' + kwargs['site'] + ' - ' + 'RPC Report' +'.docx'
)
)
iostream.seek(0)
return file_generator(iostream)
I plan to create more documents, then zip them in-memory and then serve them on the web. how could this be implmented, i have tried using the zipfile library, it seems complicated zipping in-memory files.
the following example i google around may solve my issue, but not sure how to use it.
import zipfile
import StringIO
zipped_file = StringIO.StringIO()
with zipfile.ZipFile(zipped_file, 'w') as zip:
for i, file in enumerate(files):
file.seek(0)
zip.writestr("{}.csv".format(i), file.read())
zipped_file.seek(0)
After hours of persistance, i got this working, yeahhhh
iostream = BytesIO()
tpl.get_docx().save(iostream)
iostream1 = BytesIO()
tpl1.get_docx().save(iostream1)
zip_output = StringIO.StringIO()
file = zipfile.ZipFile(zip_output, "w")
file.writestr("test.docx", iostream.getvalue())
file.writestr("test1.docx", iostream1.getvalue())
file.close()
cherrypy.response.headers['Content-Type'] = 'application/zip'
cherrypy.response.headers['Content-Disposition'] = 'attachment; filename="test.zip"'
return zip_output.getvalue()
When I create a zip file and try to open it in the same python code, why do I get BadZipFile error?
zip_file = "C:/Temp/tst_data_1022.txt"
filePath, fileName = os.path.split(zip_file)
baseFileName, fileExt = os.path.splitext(fileName)
destFtpFile = filePath + "/" + baseFileName + ".zip"
# Create the zip file and write to it
zFile = zipfile.ZipFile(destFtpFile, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True)
zFile.write(zip_file, arcname=fileName)
# Read Zip file
zfile = zipfile.ZipFile(destFtpFile, 'r')
for name in zfile.namelist():
(dirname, filename) = os.path.split(name)
print "Decompressing " + filename
filename = "C:/Temp/" + filename
fd = open(filename,"w")
fd.write(zfile.read(name))
fd.close()
The zip file is created correctly.
Error during reading:
BadZipfile: File is not a zip file
Thanks,
You are missing a call to zFile.close(), which will flush the remaining data that needs to be written to the zip file, and close the underlying file descriptor.