簡體   English   中英

在 Django 中返回 HttpResponse 后刪除 tmp 文件

[英]Removing tmp file after return HttpResponse in 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 文件,但如果我可以流式傳輸文件並從同一個請求中刪除它們會更整潔。

您可以使用 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 對象被驅逐,臨時文件應該被刪除。

供以后參考:我遇到過無法使用臨時文件進行下載的情況。 但我仍然需要在它之后刪除它們; 所以這就是我是如何做到的(我真的不想依賴 cron 作業或芹菜或 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()

大多數情況下,我們為此使用定期的 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 可以為您提供該文件。 有時這會更快。 然而,它並沒有更好地處理清理工作。

這只是使用常規的 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

一種方法是添加一個視圖來刪除此文件,並使用異步調用 (XMLHttpRequest) 從客戶端調用它。 一種變體將涉及從客戶端報告成功,以便服務器可以將此文件標記為刪除並定期進行清理工作。

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'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM