在使用StreamingHttpResponse时,当文件下载完成时,我遇到了跟踪问题。我的意图是在用户下载文件后将其删除。
执行以下操作会在终端终止服务器时返回异常。
def down(request, file_name):
if request.method == 'GET':
if file_name:
import os
fh = get_object_or_404(FileHandler, filename=file_name)
csv_path = os.path.join(fh.path, fh.filename)
csv_file = open(csv_path)
response = StreamingHttpResponse(csv_file, content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="{}"'.format(fh.filename)
csv_file.close()
# I can now delete the file using os.remove(csv_path). Not sure since response has not been returned
return response
return HttpResponseRedirect('/b2b/export/')回溯:
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 59899)
Traceback (most recent call last):
File "/usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 599, in process_request_thread
self.finish_request(request, client_address)
File "/usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 334, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/Users/Michael/.virtualenvs/scrape/lib/python2.7/site-packages/django/core/servers/basehttp.py", line 102, in __init__
super(WSGIRequestHandler, self).__init__(*args, **kwargs)
File "/usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 655, in __init__
self.handle()
File "/Users/Michael/.virtualenvs/scrape/lib/python2.7/site-packages/django/core/servers/basehttp.py", line 182, in handle
handler.run(self.server.get_app())
File "/usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/wsgiref/handlers.py", line 92, in run
self.close()
File "/usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/wsgiref/simple_server.py", line 33, in close
self.status.split(' ',1)[0], self.bytes_sent
AttributeError: 'NoneType' object has no attribute 'split'
----------------------------------------工作原理如下,但不确定何时删除文件,也不知道何时下载已完成。最重要的是如何关闭文件:
def down(request, file_name):
if request.method == 'GET':
if file_name:
import os
fh = get_object_or_404(FileHandler, filename=file_name)
csv_path = os.path.join(fh.path, fh.filename)
response = StreamingHttpResponse(open(csv_path), content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="{}"'.format(fh.filename)
return response
return HttpResponseRedirect('/b2b/export/')发布于 2016-11-21 23:52:44
尝试创建一个类,它将在文件被gc时将其删除。例如,下面这样的代码可能会起作用:
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/')发布于 2019-04-10 20:12:57
我已经尝试了@mwag的上述建议,不过是用FileWrapper。
在我的例子中,我想压缩目录,并在下载完成后删除归档文件。
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 Http404https://stackoverflow.com/questions/34149274
复制相似问题