Django4.0 文件上傳-上傳 Handlers

2022-03-16 17:44 更新

當(dāng)一個(gè)用戶上傳文件時(shí),Django 會(huì)把文件數(shù)據(jù)傳遞給 ?upload handler? —— 這是一個(gè)很小的類,它用來在上傳時(shí)處理文件數(shù)據(jù)。上傳處理模塊最初定義在 ?FILE_UPLOAD_HANDLERS ?里,默認(rèn)為:

["django.core.files.uploadhandler.MemoryFileUploadHandler",
 "django.core.files.uploadhandler.TemporaryFileUploadHandler"]

? MemoryFileUploadHandler ?和 ?TemporaryFileUploadHandler ?提供 Django 默認(rèn)文件上傳行為,小文件讀入內(nèi)存,大文件存在磁盤上。
你可以編寫自定義的 ?handlers ?來自定義 Django 如何處理文件。比如,你可以使用自定義的 ?handlers ?來強(qiáng)制處理用戶層面的配額,動(dòng)態(tài)壓縮數(shù)據(jù),渲染進(jìn)度條,甚至可以將數(shù)據(jù)發(fā)送到其他存儲(chǔ)地址而不是本地。

上傳數(shù)據(jù)的存儲(chǔ)

在保存上傳的文件之前,數(shù)據(jù)需要保存到某處。
默認(rèn)情況下,如果上傳的文件小于2.5兆,Django 將把文件的所有內(nèi)容保存到內(nèi)存里。這意味著保存文件只涉及從內(nèi)存中讀取和寫入磁盤,因此這很快。
但如果上傳的文件很大,Django 會(huì)把文件寫入系統(tǒng)臨時(shí)目錄的臨時(shí)文件里存儲(chǔ)。在類 Unix 平臺(tái)里這意味著 Django 會(huì)生成一個(gè)類似名為 ?/tmp/tmpzfp6I6.upload? 的文件。如果上傳的文件非常大,你可以查看這個(gè)文件的大小增長,因?yàn)?Django 將數(shù)據(jù)流式傳輸?shù)酱疟P上。

動(dòng)態(tài)修改上傳處理程序

有時(shí)候某些視圖需要不同的上傳行為。在這些例子里,你可以基于每個(gè)請求覆蓋上傳處理程序。默認(rèn)情況下,這個(gè)列表將包含由 ?FILE_UPLOAD_HANDLERS ?設(shè)置的上傳處理程序,但你可以像修改其他列表一樣修改這個(gè)列表。
比如,假設(shè)你正在編寫 ?ProgressBarUploadHandler ?,來提供在上傳過程中的反饋給 ?Ajax widget?。你需要添加這個(gè)處理程序到你的上傳處理模塊:

request.upload_handlers.insert(0, ProgressBarUploadHandler(request))

你或許想在這里使用 ?list.insert()? (而不是 ?append()? ),因?yàn)檫M(jìn)度條處理程序需要在其他處理程序之前使用。記住,上傳處理程序是按順序處理的。
如果你想完全替換上傳處理程序,你需要指定新列表:

request.upload_handlers = [ProgressBarUploadHandler(request)]

注解

你只能在訪問 ?request.POST? 或 ?request.FILES? 之前修改上傳處理程序,開始上傳處理后修改上傳處理程序沒有意義。如果你從讀取 ?request.POST? 或 ?request.FILES? 之后嘗試修改 ?request.upload_handlers? ,Django 會(huì)報(bào)錯(cuò)。
因此,你要盡早在視圖里修改上傳處理程序。
而且, ?request.POST? 由 ?CsrfViewMiddleware ?訪問,默認(rèn)情況下已開啟。這意味著你需要在視圖上使用 ?csrf_exempt()? 來允許你改變上傳處理程序。然后你需要在實(shí)際處理請求的函數(shù)上使用 ?csrf_protect()? 。注意這可能會(huì)讓處理程序在 CSRF 檢測完成之前開始接受文件上傳。示例:

from django.views.decorators.csrf import csrf_exempt, csrf_protect

@csrf_exempt
def upload_file_view(request):
    request.upload_handlers.insert(0, ProgressBarUploadHandler(request))
    return _upload_file_view(request)

@csrf_protect
def _upload_file_view(request):
    ... # Process request

如果你使用的是基于類的視圖,你需要在其 ?csrf_exempt()? 方法上使用 ?dispatch()?,并在實(shí)際處理請求的方法上使用 ?csrf_protect()?。示例代碼:

from django.utils.decorators import method_decorator
from django.views import View
from django.views.decorators.csrf import csrf_exempt, csrf_protect

@method_decorator(csrf_exempt, name='dispatch')
class UploadFileView(View):

    def setup(self, request, *args, **kwargs):
        request.upload_handlers.insert(0, ProgressBarUploadHandler(request))
        super().setup(request, *args, **kwargs)

    @method_decorator(csrf_protect)
    def post(self, request, *args, **kwargs):
        ... # Process request


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)