用户完成下载后,Django StreamingHttpResponse删除文件 [英] Django StreamingHttpResponse deleting file after user finishes downloading it

查看:74
本文介绍了用户完成下载后,Django StreamingHttpResponse删除文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用StreamingHttpResponse时,文件下载完成时,我在跟踪问题.我的意图是在用户下载文件后将其删除.

I am having problem tracking when a file download has been completed when StreamingHttpResponse is used. My intention is to delete the file once it has been downloaded by the user.

执行以下操作会在终端终止服务器方面返回异常.

Doing the following returned an exception in terminal killing the server.

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'
----------------------------------------

有效的方法如下,但是不确定何时删除文件或何时完成下载.最重要的是如何关闭文件:

What works is as follows but am not sure when to delete the file or know when download has been completed. Most importantly how to close the file:

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/')

推荐答案

尝试创建一个类,该类将在文件被gc删除时删除.例如,类似下面的内容可能会起作用:

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/')

这篇关于用户完成下载后,Django StreamingHttpResponse删除文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆