首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Django StreamingHttpResponse下载完成后删除文件

Django StreamingHttpResponse下载完成后删除文件
EN

Stack Overflow用户
提问于 2015-12-08 14:17:15
回答 2查看 1.8K关注 0票数 3

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

执行以下操作会在终端终止服务器时返回异常。

代码语言:javascript
复制
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/')

回溯:

代码语言:javascript
复制
----------------------------------------
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'
----------------------------------------

工作原理如下,但不确定何时删除文件,也不知道何时下载已完成。最重要的是如何关闭文件:

代码语言:javascript
复制
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/')
EN

回答 2

Stack Overflow用户

发布于 2016-11-21 23:52:44

尝试创建一个类,它将在文件被gc时将其删除。例如,下面这样的代码可能会起作用:

代码语言:javascript
复制
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/')
票数 0
EN

Stack Overflow用户

发布于 2019-04-10 20:12:57

我已经尝试了@mwag的上述建议,不过是用FileWrapper。

在我的例子中,我想压缩目录,并在下载完成后删除归档文件。

代码语言:javascript
复制
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
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34149274

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档