django文件上傳


當django處理文件上傳時,文件數據被打包封裝在request.FILES中

1、基本文件上傳

首先寫一個form表單,它必須包含一個FileField文件字段:

#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()的變量名來的

注意:request.FILES只有在請求方法為POST,並且提交請求的<form>具有enctype="multipart/form-data"屬性時才有效,否則request.FILES將為空

下面是一個接收上傳文件的視圖范例:

#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()方法

UploadedFile.multipls_chunks(chunk_size=None):如果上傳的文件足夠大,需要在多個塊中讀取,則返回True,默認為True,默認chunk_size為2.5M,也可以指定

 UploadedFile.chunks(chunk_size=None):生成器返回文件的塊,如果multiple_chunks()為True,則因該盡量使用此方法而不是read()方法,在實踐中通常最簡單的方法就是一直使用chunks(),通過循環chunks()來存儲文件數據

UploadedFile長用的一些屬性:

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>

2、使用模型處理上傳的文件

如果是通過模型層的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})

3、同時上傳多個文件

如果要使用一個表單字段同時上傳多個文件,需設置字段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})

4、上傳文件處理器

當用戶上傳一個文件的時候,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如何處理文件。例如,根據級別不同限制用戶的磁盤配額,在運行中壓縮數據,渲染進度條,甚至是轉存到另一個儲存位置,而不把它存到本地。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM