當django處理文件上傳時,文件數據被打包封裝在request.FILES中html
首先寫一個form表單,它必須包含一個FileField文件字段:django
#forms.py from django import forms class UploadFileForm(forms.Form): title = forms.CharField(max_length=50) file = forms.FileField()
處理這個表單的視圖將在request.FILES中收到文件數據,能夠用request.FILES['file']來獲取上傳文件的具體數據,其中的鍵值'file'是根據form表單中字段file=forms.FileField()的變量名來的app
注意:request.FILES只有在請求方法爲POST,而且提交請求的<form>具備enctype="multipart/form-data"屬性時纔有效,不然request.FILES將爲空函數
下面是一個接收上傳文件的視圖範例:post
#views.py from django.http import HttpResponse from django.shortcuts import render from .forms import UploadFileForm from django.conf import settings #建立函數處理上傳文件數據 def handle_uploaded_file(f,filename): filename_path = f'{settings.MEDIA_ROOT}{filename}' #生成文件名及路徑 with open(filename_path,'wb+') as destination: for chunk in f.chunks(): destination.write(chunk) destination.close() def index(request): if request.method == 'POST': forms = UploadFileForm(request.POST,request.FILES) if forms.is_valid(): handle_uploaded_file(request.FILES['file'],filename=request.FILES.get('file')) return HttpResponse('file for upload ok') print(forms) else: forms = UploadFileForm() print(forms) return render(request,'index.html',context={'forms':forms})
在文件上傳期間,實際文件數據存儲在request.FILES,此字典中的每一個條目都是一個UploadedFile對象,此對象包括如下方法和屬性:編碼
UploadedFile.read():從文件中讀取整個上傳的數據,當心這個方法,若是上傳的文件太大,若是你試圖將它讀入內存,它會消耗系統大量內存,你可使用cunks()方法url
UploadedFile.multipls_chunks(chunk_size=None):若是上傳的文件足夠大,須要在多個塊中讀取,則返回True,默認爲True,默認chunk_size爲2.5M,也能夠指定spa
UploadedFile.chunks(chunk_size=None):生成器返回文件的塊,若是multiple_chunks()爲True,則因該儘可能使用此方法而不是read()方法,在實踐中一般最簡單的方法就是一直使用chunks(),經過循環chunks()來存儲文件數據code
UploadedFile長用的一些屬性:orm
UploadedFile.name:上傳文件的名稱
UploadedFile.size:上傳文件大小
UploadedFile.content_type:隨文件一塊兒上傳的內容類型標題(如:text/plain或application/pdf)
UploadedFile.content_type_extra:包含傳遞給content-type標頭的額外參數的字典
UploadedFile.charset:隊友text/content-types提供的utf8字符集編碼
其它文件代碼:
#urls.py from django.contrib import admin from django.urls import path,re_path from testfileile import views urlpatterns = [ path('admin/', admin.site.urls), re_path(r'^$',views.index,name='index'), #settings.py配置媒體文件上傳目錄和訪問路徑 MEDIA_ROOT = os.path.join(BASE_DIR,'static/images/') MEDIA_URL = '/media/' #index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>index</title> </head> <body> <form method="post" action="/" enctype="multipart/form-data"> #上傳文件時必須包含enctype屬性 {% csrf_token %} {{ forms }}<br> <input type="submit" value="提交"> </form> </body> </html>
若是是經過模型層的model來指定上傳文件的保存方式,使用ModelForm更方便,調用form.save()的時候,文件對象會保存在相應的FileField的upload_to參數指定的地方,實際文件會存儲在settings配置文件中MEDIA_ROOT指定的絕對路徑加upload_to子目錄下
看以下示例:
#models.py from django.db import models class ModelFileField(models.Model): title = models.CharField(max_length=200) file = models.FileField(upload_to='photos/%Y/%m/%d') #將格式化爲時間目錄 #froms.py經過模型建立表單 from .models import ModelFileField from django.forms import ModelForm class ModelFormFile(ModelForm): class Meta: model = ModelFileField fields = "__all__" #views.py from django.http import HttpResponse from django.shortcuts import render from .forms import ModelFormFile def upload_file(request): if request.method == 'POST': forms = ModelFormFile(request.POST,request.FILES) if forms.is_valid(): forms.save(commit=True) #文件直接保存在model中的upload_to指定的子目錄下 return HttpResponse('ok') else: forms = ModelFormFile() return render(request,'upload.html',{'forms':forms}) #settings.py MEDIA_ROOT = os.path.join(BASE_DIR,'static/images/') MEDIA_URL = '/media/' #upload.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>upload file</title> </head> <body> <form method="post" action="{% url 'upload' %}" enctype="multipart/form-data"> {% csrf_token %} {{ forms }}<br> <input type="submit" value="提交"> </form> </body> </html>
若是要手動指定對象,只需將文件對象request.FILES賦值給模型中的文件字段便可:
但須要注意,若有其它字段必須容許爲空,不然將引起異常!
#views.py from django.http import HttpResponse from django.shortcuts import render from .forms import ModelFormFile from .models import ModelFileField def upload_file(request): if request.method == 'POST': forms = ModelFormFile(request.POST,request.FILES) if forms.is_valid(): instance = ModelFileField(file=request.FILES['file']) #將文件數據指定到模型字段 instance.save() #forms.save(commit=True) return HttpResponse('ok') else: forms = ModelFormFile() return render(request,'upload.html',{'forms':forms})
若是要使用一個表單字段同時上傳多個文件,需設置字段HTML標籤的mulpiple屬性爲True,在django表單中設置小部件HTML的屬性:
#forms.py from django import forms from .models import ModelFileField from django.forms import ModelForm class ModelFormFile(ModelForm): class Meta: model = ModelFileField fields = "__all__" widgets = { 'file':forms.ClearableFileInput(attrs={'multiple':True}) } #上面模型的基礎上,建立的forms表單添加HTML屬性multiple
在視圖中存儲多個文件則須要經過getlist方法獲取多個文件的列表,而後循環存儲到數據並保存便可:
#views.py from django.http import HttpResponse from django.shortcuts import render from .forms import ModelFormFile from .models import ModelFileField def upload_file(request): if request.method == 'POST': forms = ModelFormFile(request.POST,request.FILES) if forms.is_valid(): for i in request.FILES.getlist('file'): #獲取文件列表 instance = ModelFileField(file=i) instance.save() return HttpResponse('ok') else: forms = ModelFormFile() return render(request,'upload.html',{'forms':forms})
當用戶上傳一個文件的時候,Django會把文件數據傳遞給上傳文件處理器一個類。
上傳處理器的配置定義在FILE_UPLOAD_HANDLERS中,默認爲:
["django.core.files.uploadhandler.MemoryFileUploadHandler", "django.core.files.uploadhandler.TemporaryFileUploadHandler"]
MemoryFileUploadHandler和TemporaryFileUploadHandler定義了Django的默認文件上傳行爲:將小文件讀取到內存中,大文件放置在磁盤中。
在你保存上傳文件以前,數據須要儲存在某個地方。一般,若是上傳文件小於2.5MB,Django會把整個內容存到內存。 這意味着,文件的保存僅僅涉及到內存中的讀取和磁盤的寫入,因此很是快。可是,若是上傳的文件很大,Django會把它寫入一個臨時文件,儲存在你的系統臨時目錄中。在類Unix的平臺下,Django會生成一個文件,名稱相似於/tmp/tmpzfp6I6.upload。
咱們能夠編寫自定義的處理器,來定製Django如何處理文件。例如,根據級別不一樣限制用戶的磁盤配額,在運行中壓縮數據,渲染進度條,甚至是轉存到另外一個儲存位置,而不把它存到本地。