2๐
I have tried the above suggestion by @mwag; however with FileWrapper.
In my case, wanted to zip up directories and get rid of the archive when download is done.
import os, time, zipfile
from django.http import StreamingHttpResponse
from wsgiref.util import FileWrapper
class FileDeleteWrapper(FileWrapper):
def __init__(self, filepath, *args, **kwargs):
self.filepath = filepath
super(FileDeleteWrapper, self).__init__(*args, **kwargs)
def __del__(self, *args, **kwargs):
os.remove(self.filepath)
# View function
def zipFiles(request, assetId):
asset = get_object_or_404(Asset, id=assetId)
try:
files = File.objects.filter(asset=asset)
prefix = str(time.time()) +'_'
zipPath = os.path.join(
settings.ZIPPED_FILES_DIR,
prefix + asset.label+'.zip'
)
z = zipfile.ZipFile(zipPath, 'w', zipfile.ZIP_DEFLATED)
for f in files:
path = os.path.join(
mainSet.MEDIA_ROOT,
str(f.file)
)
z.write(path, str(f))
z.close()
chunkSize = 16384
response = StreamingHttpResponse(
FileDeleteWrapper(
filepath = zipPath,
filelike=open(zipPath, 'rb'),
blksize=chunkSize
)
)
response['Content-Length'] = os.path.getsize(zipPath)
response['Content-Disposition'] = "attachment; filename=%s" % asset.label+'.zip'
return response
except Exception as e:
if mainSet.DEBUG:
print(type(e))
else:
# log expception
raise Http404
๐คAbbas
1๐
Try creating a class that will delete the file when it is gcโd. For example, something like the below might work:
class open_then_delete(object):
def __init__(self, filename, mode='rb'):
self.filename = filename
self.file_obj = open(filename, mode)
def __del__(self):
self.close()
def close(self):
if self.file_obj:
self.file_obj.close()
self.file_obj = None
self.cleanup()
def cleanup(self):
if self.filename:
try:
sys.stderr.write('open_then_delete: del ' + self.filename)
os.remove(self.filename)
except:
pass
self.filename = None
def __getattr__(self, attr):
return getattr(self.file_obj, attr)
def __iter__(self):
return iter(self.file_obj)
# below is your code, modified to use use_then_delete
def down(request, file_name):
if request.method == 'GET':
if file_name:
import os
fh = get_object_or_404(FileHandler, filename=file_name)
csv = open_then_delete(os.path.join(fh.path, fh.filename))
response = StreamingHttpResponse(csv.open(), content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="{}"'.format(fh.filename)
return response
return HttpResponseRedirect('/b2b/export/')
๐คmwag
- [Django]-What is the proper process for validating and saving data with with Django/Django Rest Framework regardless the data source?
- [Django]-What is Django's migration?
Source:stackexchange.com