Django的form表單之文件上傳
在生成input標簽的時候可以指定input標簽的類型為file類型
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h4>{{ error_message }}</h4>
<form action="/index/" method="post">
{% csrf_token %}
<p><input type="file" name="up_file"></p>
<input type="submit">
</form>
</body>
</html>
此時,在網頁上頁示如下
如果網頁上提交的是用戶名和密碼等,通過鍵值對發送到服務端。
一組鍵值代表一個標簽及標簽對應的值。
在網頁上選擇一張圖片,並使用post
方式提交,在服務端打印request.POST
def index(request):
if request.method=="POST":
print(request.POST)
return render(request,"index.html",locals())
打印的信息如下:
<QueryDict: {'csrfmiddlewaretoken': ['opmSmENIrgdGJJN'], 'up_file': ['1.png']}>
提交的文件名也在這個字典中,取出這個文件名
def index(request):
if request.method=="POST":
print(request.POST.get("up_file"))
print(type(request.POST.get("up_file")))
return render(request,"index.html",locals())
打印結果如下:
1.png
<class 'str'>
想取出的是上傳的文件,然而取出來的卻是上傳的文件的文件名
由此可知,上傳的文件沒有跟form表單提交的數據在一起
因為上傳的文件通常大小比較大,所以Django默認會把上傳的文件放在一個具體的文件夾中
打印request.FILES
的信息
def index(request):
if request.method=="POST":
print(request.POST.get("up_file"))
print(type(request.POST.get("up_file")))
print("files:",request.FILES)
return render(request,"index.html",locals())
打印結果如下
1.png
<class 'str'>
files: <MultiValueDict: {}>
request.FILES
打印的結果是一個空的字典,問題出在上傳文件的方式上
由於上傳文件時在客戶端與服務端傳輸的是二進制數據,與字符串數據不一樣。
傳輸二進制數據,不管是在form表單,還是在Ajax中,都有自己的傳輸方式。
在form表單中,上傳文件時要使用分片傳輸的方式。
修改index.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h4>{{ error_message }}</h4>
<form action="/index/" method="post" enctype="multipart/form-data">
{% csrf_token %}
<p><input type="file" name="up_file"></p>
<input type="submit">
</form>
</body>
</html>
重新上傳文件,在服務端打印信息如下
None
<class 'NoneType'>
files: <MultiValueDict: {'up_file': [<InMemoryUploadedFile: 1.png (image/png)>]}>
根據打印結果,request.FILES
中可以看到上傳的文件
打印結果是一個字典類型,字典的鍵是form表單中定義的標簽的name屬性值,而其值是所上傳的文件的對象
打印上傳文件的對象
def index(request):
if request.method=="POST":
print("files:",request.FILES.get("up_file"))
print(type(request.FILES.get("up_file")))
return render(request,"index.html",locals())
打印結果
files: 1.png
<class 'django.core.files.uploadedfile.InMemoryUploadedFile'>
結果顯示所取得的文件的類型是一個在內存中的上傳文件
獲取上傳文件在內存中的名字
def index(request):
if request.method=="POST":
print(type(request.FILES.get("up_file")))
file_obj=request.FILES.get("up_file")
print(file_obj.name)
return render(request,"index.html",locals())
打印結果如下
<class 'django.core.files.uploadedfile.InMemoryUploadedFile'>
1.png
既然知道了文件在內存中的名字,就可以在服務端寫入這個文件
def index(request):
if request.method=="POST":
file_obj=request.FILES.get("up_file")
f1=open(file_obj.name,"wb")
for i in file_obj.chunks():
f1.write(i)
f1.close()
return render(request,"index.html",locals())
再次選擇上傳文件,提交后,就可以在服務端后台看到所上傳的文件
可以在settings.py文件中設定上傳文件的路徑,或者在打開文件句柄的時候進行路徑拼接來把上傳的文件保存在指定的目錄下