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

rqqzpn5f  于 12个月前  发布在  Go
关注(0)|答案(7)|浏览(160)

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

wrapper = FileWrapper(file(path))
response = HttpResponse(wrapper, content_type='text/plain')
response['Content-Length'] = os.path.getsize(path)
return response

字符串
有没有一种方法可以在返回响应后删除文件?使用回调函数或其他方法?我可以只创建一个cron来删除所有的tmp文件,但是如果我可以从同一个请求中流式传输文件并删除它们,那就更整洁了。

qmb5sa22

qmb5sa221#

您可以使用NamedTemporaryFile:

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对象被驱逐,临时文件应该被删除。

55ooxyrt

55ooxyrt2#

供今后参考:我只是有一个情况,我不能使用临时文件下载。但我仍然需要删除后,它;所以这里是我如何做到这一点(我真的不想依赖cron作业或celery 或wossnames,它是一个非常小的系统,我希望它保持这种方式)。

def plug_cleaning_into_stream(stream, filename):
    try:
        closer = getattr(stream, 'close')
        #define a new function that still uses the old one
        def new_closer():
            closer()
            os.remove(filename)
            #any cleaning you need added as well
        #substitute it to the old close() function
        setattr(stream, 'close', new_closer)
    except:
        raise

字符串
然后我把用于响应的流插入其中。

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()

kdfy810k

kdfy810k3#

大多数情况下,我们使用周期性的cron作业。
Django已经有了一个cron任务来清理丢失的会话。你已经在运行它了,对吗?
请访问http://docs.djangoproject.com/en/dev/topics/http/sessions/#clearing-the-session-table
您需要在应用程序中使用另一个类似的命令来清理旧文件。
看到这个http://docs.djangoproject.com/en/dev/howto/custom-management-commands/
另外,你可能并不是真的从Django发送这个文件。有时你可以通过在Apache使用的目录中创建文件并重定向到一个URL来获得更好的性能,这样Apache就可以为你提供文件。有时这会更快。但是,它并没有更好地处理清理。

klh5stk1

klh5stk14#

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

g6baxovj

g6baxovj5#

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

# something generates a file at filepath

from subprocess import Popen

# open file
with open(filepath, "rb") as fid:
    filedata = fid.read()

# remove the file
p = Popen("rm %s" % filepath, shell=True)

# make response
response = HttpResponse(filedata, content-type="text/plain")

return response

字符串

gmol1639

gmol16396#

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'

字符串

cnh2zyt3

cnh2zyt37#

你可以通过try / finally来实现:

try:
    HttpResponse(...) / FileResponse(...)
finally:
    os.remove(tmp_file) / shutil.rmtree(path_to_tmp_file)

字符串

相关问题