在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Python/ 文件上傳
點(diǎn)擊劫持保護(hù)
安全問(wèn)題歸檔
Model 類參考
將遺留數(shù)據(jù)庫(kù)整合到Django
關(guān)聯(lián)對(duì)象參考
內(nèi)建基于類的視圖的API
聚合
Django 中的用戶認(rèn)證
django.contrib.humanize
Django管理文檔生成器
分頁(yè)
使用Django輸出CSV
加密簽名
文件儲(chǔ)存API
安全
Django中的測(cè)試
國(guó)際化和本地化
為Django編寫(xiě)首個(gè)補(bǔ)丁
條件表達(dá)式
日志
模型元選項(xiàng)
部署靜態(tài)文件
執(zhí)行查詢
使用Django認(rèn)證系統(tǒng)
基于類的視圖
中間件
編寫(xiě)自定義的django-admin命令
Django 的設(shè)置
格式本地化
數(shù)據(jù)庫(kù)訪問(wèn)優(yōu)化
錯(cuò)誤報(bào)告
基于類的內(nèi)建通用視圖
編寫(xiě)自定義存儲(chǔ)系統(tǒng)
編寫(xiě)你的第一個(gè) Django 程序 第3部分
編寫(xiě)數(shù)據(jù)庫(kù)遷移
使用表單
編寫(xiě)你的第一個(gè) Django 程序 第2部分
編寫(xiě)你的第一個(gè) Django 程序 第1部分
如何使用會(huì)話
系統(tǒng)檢查框架
新手入門(mén)
信號(hào)
編寫(xiě)視圖
如何使用WSGI 部署
編寫(xiě)你的第一個(gè)Django應(yīng)用,第6部分
常見(jiàn)的網(wǎng)站應(yīng)用工具
Widgets
內(nèi)建的視圖
模型實(shí)例參考
視圖層
Django中的密碼管理
高級(jí)教程:如何編寫(xiě)可重用的應(yīng)用
國(guó)際化和本地化
"本地特色"附加功能
TemplateResponse 和 SimpleTemplateResponse
模式編輯器
文件上傳
快速安裝指南
部署 Django
表單 API
表單素材 ( <code>Media</code> 類)
管理文件
其它核心功能
查找 API 參考
表單
Admin
數(shù)據(jù)庫(kù)函數(shù)
自定義查找
使用基于類的視圖處理表單
管理操作
開(kāi)發(fā)過(guò)程
編寫(xiě)你的第一個(gè)Django應(yīng)用,第5部分
進(jìn)行原始的sql查詢
模型層
多數(shù)據(jù)庫(kù)
編寫(xiě)你的第一個(gè) Django 程序 第4部分
Django安全
Django 初探
Django異常
重定向應(yīng)用
按需內(nèi)容處理
管理器
視圖裝飾器
驗(yàn)證器
使用Django輸出PDF
File對(duì)象
Django 的快捷函數(shù)
基于類的通用視圖 —— 索引
為模型提供初始數(shù)據(jù)
模板層
URL調(diào)度器
中間件
模型

文件上傳

當(dāng)Django在處理文件上傳的時(shí)候,文件數(shù)據(jù)被保存在request. FILES (更多關(guān)于 request 對(duì)象的信息 請(qǐng)查看 請(qǐng)求和響應(yīng)對(duì)象)。這篇文檔闡述了文件如何上傳到內(nèi)存和硬盤(pán),以及如何自定義默認(rèn)的行為。

警告

允許任意用戶上傳文件是存在安全隱患的。更多細(xì)節(jié)請(qǐng)?jiān)?a rel="nofollow" >用戶上傳的內(nèi)容中查看有關(guān)安全指導(dǎo)的話題。

基本的文件上傳

考慮一個(gè)簡(jiǎn)單的表單,它含有一個(gè)FileField

# In forms.py...
from django import forms

class UploadFileForm(forms.Form):
    title = forms.CharField(max_length=50)
    file = forms.FileField()

處理這個(gè)表單的視圖會(huì)在request中接受到上傳文件的數(shù)據(jù)。FILES是個(gè)字典,它包含每個(gè)FileField的鍵 (或者 ImageField,FileField的子類)。這樣的話就可以用request.FILES['file']來(lái)存放表單中的這些數(shù)據(jù)了。

注意request.FILES會(huì)僅僅包含數(shù)據(jù),如果請(qǐng)求方法為POST,并且發(fā)送請(qǐng)求的<form>擁有enctype="multipart/form-data"屬性。否則request.FILES為空。

大多數(shù)情況下,你會(huì)簡(jiǎn)單地從request向表單中傳遞數(shù)據(jù),就像綁定上傳文件到表單描述的那樣。這樣類似于:

from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from .forms import UploadFileForm

# Imaginary function to handle an uploaded file.
from somewhere import handle_uploaded_file

def upload_file(request):
    if request.method == 'POST':
        form = UploadFileForm(request.POST, request.FILES)
        if form.is_valid():
            handle_uploaded_file(request.FILES['file'])
            return HttpResponseRedirect('/success/url/')
    else:
        form = UploadFileForm()
    return render_to_response('upload.html', {'form': form})

注意我們必須向表單的構(gòu)造器中傳遞request.FILES。這是文件數(shù)據(jù)綁定到表單的方法。

這里是一個(gè)普遍的方法,可能你會(huì)采用它來(lái)處理上傳文件:

def handle_uploaded_file(f):
    with open('some/file/name.txt', 'wb+') as destination:
        for chunk in f.chunks():
            destination.write(chunk)

遍歷UploadedFile.chunks(),而不是使用read(),能確保大文件并不會(huì)占用系統(tǒng)過(guò)多的內(nèi)存。

UploadedFile對(duì)象也擁有一些其他的方法和屬性;完整參考請(qǐng)見(jiàn)UploadedFile。

使用模型處理上傳文件

如果你在Model上使用FileField保存文件,使用ModelForm可以讓這個(gè)操作更加容易。調(diào)用form.save()的時(shí)候,文件對(duì)象會(huì)保存在相應(yīng)的FileFieldupload_to參數(shù)指定的地方。

from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import ModelFormWithFileField

def upload_file(request):
    if request.method == 'POST':
        form = ModelFormWithFileField(request.POST, request.FILES)
        if form.is_valid():
            # file is saved
            form.save()
            return HttpResponseRedirect('/success/url/')
    else:
        form = ModelFormWithFileField()
    return render(request, 'upload.html', {'form': form})

如果你手動(dòng)構(gòu)造一個(gè)對(duì)象,你可以簡(jiǎn)單地把文件對(duì)象從request.FILE賦值給模型:

from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import UploadFileForm
from .models import ModelWithFileField

def upload_file(request):
    if request.method == 'POST':
        form = UploadFileForm(request.POST, request.FILES)
        if form.is_valid():
            instance = ModelWithFileField(file_field=request.FILES['file'])
            instance.save()
            return HttpResponseRedirect('/success/url/')
    else:
        form = UploadFileForm()
    return render(request, 'upload.html', {'form': form})

上傳處理器

當(dāng)用戶上傳一個(gè)文件的時(shí)候,Django會(huì)把文件數(shù)據(jù)傳遞給上傳處理器 – 一個(gè)小型的類,會(huì)在文件數(shù)據(jù)上傳時(shí)處理它。上傳處理器在FILE_UPLOAD_HANDLERS中定義,默認(rèn)為:

("django.core.files.uploadhandler.MemoryFileUploadHandler",
 "django.core.files.uploadhandler.TemporaryFileUploadHandler",)

MemoryFileUploadHandlerTemporaryFileUploadHandler一起提供了Django的默認(rèn)文件上傳行為,將小文件讀取到內(nèi)存中,大文件放置在磁盤(pán)中。

你可以編寫(xiě)自定義的處理器,來(lái)定制Django如何處理文件。例如,你可以使用自定義處理器來(lái)限制用戶級(jí)別的配額,在運(yùn)行中壓縮數(shù)據(jù),渲染進(jìn)度條,甚至是向另一個(gè)儲(chǔ)存位置直接發(fā)送數(shù)據(jù),而不把它存到本地。關(guān)于如何自定義或者完全替換處理器的行為,詳見(jiàn)編寫(xiě)自定義的上傳處理器。

上傳數(shù)據(jù)在哪里儲(chǔ)存

在你保存上傳文件之前,數(shù)據(jù)需要儲(chǔ)存在某個(gè)地方。

通常,如果上傳文件小于2.5MB,Django會(huì)把整個(gè)內(nèi)容存到內(nèi)存。這意味著,文件的保存僅僅涉及到從內(nèi)存讀取和寫(xiě)到磁盤(pán),所以非常快。

但是,如果上傳的文件很大,Django會(huì)把它寫(xiě)入一個(gè)臨時(shí)文件,儲(chǔ)存在你系統(tǒng)的臨時(shí)目錄中。在類Unix的平臺(tái)下,你可以認(rèn)為Django生成了一個(gè)文件,名稱類似于/tmp/tmpzfp6I6.upload。如果上傳的文件足夠大,你可以觀察到文件大小的增長(zhǎng),由于Django向磁盤(pán)寫(xiě)入數(shù)據(jù)。

這些特定值 – 2.5 MB,/tmp,以及其它 -- 都僅僅是"合理的默認(rèn)值",它們可以自定義,這會(huì)在下一節(jié)中描述。

更改上傳處理器的行為

Django的文件上傳處理器的行為由一些設(shè)置控制。詳見(jiàn)文件上傳設(shè)置。

在運(yùn)行中更改上傳處理器

有時(shí)候一些特定的視圖需要不同的上傳處理器。在這種情況下,你可以通過(guò)修改request.upload_handlers,為每個(gè)請(qǐng)求覆蓋上傳處理器。通常,這個(gè)列表會(huì)包含FILE_UPLOAD_HANDLERS提供的上傳處理器,但是你可以把它修改為其它列表。

例如,假設(shè)你編寫(xiě)了ProgressBarUploadHandler,它會(huì)在上傳過(guò)程中向某類AJAX控件提供反饋。你可以像這樣將它添加到你的上傳處理器中:

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

在這中情況下你可能想要使用list.insert()(而不是append()),因?yàn)檫M(jìn)度條處理器需要在任何其他處理器 之前執(zhí)行。要記住,多個(gè)上傳處理器是按順序執(zhí)行的。

如果你想要完全替換上傳處理器,你可以賦值一個(gè)新的列表:

request.upload_handlers = [ProgressBarUploadHandler()]

注意

你只可以在訪問(wèn)request.POST或者request.FILES之前修改上傳處理器-- 在上傳處理工作執(zhí)行之后再修改上傳處理就毫無(wú)意義了。如果你在讀取request.FILES之后嘗試修改request.upload_handlers,Django會(huì)拋出異常。

所以,你應(yīng)該在你的視圖中盡早修改上傳處理器。

CsrfViewMiddleware 也會(huì)訪問(wèn)request.POST,它是默認(rèn)開(kāi)啟的。意思是你需要在你的視圖中使用csrf_exempt(),來(lái)允許你修改上傳處理器。接下來(lái)在真正處理請(qǐng)求的函數(shù)中,需要使用csrf_protect()。注意這意味著處理器可能會(huì)在CSRF驗(yàn)證完成之前開(kāi)始接收上傳文件。例如:

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

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

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

譯者:Django 文檔協(xié)作翻譯小組,原文:Overview。

本文以 CC BY-NC-SA 3.0 協(xié)議發(fā)布,轉(zhuǎn)載請(qǐng)保留作者署名和文章出處。

Django 文檔協(xié)作翻譯小組人手緊缺,有興趣的朋友可以加入我們,完全公益性質(zhì)。交流群:467338606。