Python 在django中返回HttpResponse后删除tmp文件

Python 在django中返回HttpResponse后删除tmp文件,python,django,Python,Django,我使用以下django/python代码将文件流式传输到浏览器: wrapper = FileWrapper(file(path)) response = HttpResponse(wrapper, content_type='text/plain') response['Content-Length'] = os.path.getsize(path) return response 有没有办法在返回响应后删除该文件?使用回调函数还是什么? 我可以制作一个cron来删除所有tmp文件,但是如果

我使用以下django/python代码将文件流式传输到浏览器:

wrapper = FileWrapper(file(path))
response = HttpResponse(wrapper, content_type='text/plain')
response['Content-Length'] = os.path.getsize(path)
return response
有没有办法在返回响应后删除该文件?使用回调函数还是什么?
我可以制作一个cron来删除所有tmp文件,但是如果我可以流式传输文件并从同一个请求中删除它们,那就更整洁了。

一种方法是添加一个视图来删除这个文件,并使用异步调用(XMLHttpRequest)从客户端调用它。这种方法的一种变体是在成功后从客户端返回报告,以便服务器可以将此文件标记为删除,并定期进行清理。

通常,我们使用定期cron作业来完成此操作

Django已经有一个cron任务来清理丢失的会话。你已经在运行它了,对吗

在应用程序中,您需要另一个类似于此的命令来清理旧文件

看到这个了吗


此外,您可能不是真的从Django发送此文件。有时,通过在Apache使用的目录中创建文件并重定向到URL,以便Apache可以为您提供该文件,您可以获得更好的性能。有时这会更快。但是,它不能更好地处理清理。

您可以使用命名的临时文件:

from django.core.files.temp import NamedTemporaryFile
def send_file(request):
    newfile = NamedTemporaryFile(suffix='.txt')
    # save your data to newfile.name
    wrapper = FileWrapper(newfile)
    response = HttpResponse(wrapper, content_type=mime_type)
    response['Content-Disposition'] = 'attachment; filename=%s' % os.path.basename(modelfile.name)
    response['Content-Length'] = os.path.getsize(modelfile.name)
    return response

一旦newfile对象被逐出,就应该删除临时文件。

这只是使用常规python方法(非常简单的示例):

供日后参考: 我只是遇到了一个无法使用临时文件进行下载的情况。 但我仍然需要删除后,它;我就是这样做的(我真的不想依赖cron-jobs、芹菜或wossnames,这是一个非常小的系统,我希望它保持这种状态)

然后我只需要获取用于响应的流,并插入其中

def send_file(request, filename):
    with io.open(filename, 'rb') as ready_file:
        plug_cleaning_into_stream(ready_file, filename)
        response = HttpResponse(ready_file.read(), content_type='application/force-download')
        # here all the rest of the heards settings
        # ...
        return response
我知道这又快又脏,但它很管用。我怀疑对于一个每秒有数千个请求的服务器来说,这是有效率的,但这不是我的情况(最多一分钟几十个)


编辑:忘了精确地说明我在处理下载时无法放入内存的非常大的文件。这就是为什么我要使用一个
BufferedReader
(它位于
io.open()
下面)

Python 3.7,Django 2.2.5

from tempfile import NamedTemporaryFile
from django.http import HttpResponse
with NamedTemporaryFile(suffix='.csv', mode='r+', encoding='utf8') as f:
    f.write('\uFEFF')  # BOM
    f.write('sth you want')

    # ref: https://docs.python.org/3/library/tempfile.html#examples
    f.seek(0)
    data=f.read()

    response = HttpResponse(data, content_type="text/plain")
    response['Content-Disposition'] = 'inline; filename=export.csv'

对我来说,这听起来不是个好主意——不需要从客户端向服务器发送额外的消息。定期清理临时文件要好得多。@loevborg:OP要求提供替代方案。因此
我可以制作一个cron来删除所有tmp文件,但这样会更整洁…
一旦新文件对象被逐出,临时文件应该被删除。
:是否有一个内置机制来自动删除
NamedTemporaryFile
实例?如果我是正确的,一旦对对象的所有引用都被销毁,垃圾收集器就会销毁对象。当您退出send_file函数时,不应该再有对newfile对象的引用,因此可以在下次GC运行时删除它。NamedTemporaryFile的析构函数状态为:def close(self):if not self.close_调用:self.close_called=True self.file.close()self.unlink(self.name)def u del_;(self):self.close()fylb,没错,但不能保证对象将被垃圾收集并调用其del方法。谁知道垃圾收集器会做什么?最好定期手动清理。您可以在Apache中使用
mod xsendfile
而不是重定向,然后这是一个请求,您可以控制文件访问。请为您的答案提供一些解释,并避免发布仅代码的答案。
def send_file(request, filename):
    with io.open(filename, 'rb') as ready_file:
        plug_cleaning_into_stream(ready_file, filename)
        response = HttpResponse(ready_file.read(), content_type='application/force-download')
        # here all the rest of the heards settings
        # ...
        return response
from tempfile import NamedTemporaryFile
from django.http import HttpResponse
with NamedTemporaryFile(suffix='.csv', mode='r+', encoding='utf8') as f:
    f.write('\uFEFF')  # BOM
    f.write('sth you want')

    # ref: https://docs.python.org/3/library/tempfile.html#examples
    f.seek(0)
    data=f.read()

    response = HttpResponse(data, content_type="text/plain")
    response['Content-Disposition'] = 'inline; filename=export.csv'