Trong phần này chúng ta sẽ tạo form thực hiện chức năng upload file lên thư mục gốc của server.
Các hàm view mà chúng ta đã viết đều nhận một tham số đầu vào là một đối tượng HttpRequest,
đối tượng này lưu trữ những thông tin về dữ liệu được gửi từ người dùng lên server, ví dụ như khi bạn nhập localhost:8000/
thì trình duyệt sẽ tạo một đối tượng lưu trữ những thông tin chẳng hạn như phương thức gửi lên, địa chỉ ip, url, ngày giờ gửi… rồi nén tất cả những thông tin đó lại và gửi đến server của chúng ta qua giao thức HTTP. Khi dữ liệu được gửi đến, server Django sẽ tạo một đối tượng thuộc lớp HttpRequest
và đưa những thông tin được gửi đến vào đối tượng này rồi truyền vào làm tham số cho hàm view tương ứng, trong hàm view đó chúng ta có thể lấy các thông tin từ đối tượng HttpRequest
này để xử lý.
Bên trong lớp HttpRequest
có một thuộc tính tên là FILES,
thuộc tính này lưu trữ những thông tin về file được gửi lên để chúng ta xử lý. Ngoài ra nếu muốn bạn có thể tìm hiểu các thuộc tính khác ở đây.
Bạn cũng nên lưu ý là vì một số vấn đề bảo mật nên bạn nên cấu hình server chỉ cho phép nhận các file có dung lượng giới hạn tại mức nào đó thôi, ví dụ như chỉ cho phép nhận từ 2 đến 5 MB đối với như file ảnh… Mình sẽ đề cập đến vấn đề này trong bài khác.
Tạo form upload file
Chúng ta tạo một app mới với tên là file_uploader:
C:\Project\mysite>python manage.py startapp file_uploader
Chúng ta khai báo app cho project.
INSTALLED_APPS = [ #... 'file_uploader', #... ]
Kế tiếp chúng ta tạo file forms.py
bên trong thư mục file_uploader:
from django import forms class UploadFileForm(forms.Form): title = forms.CharField(max_length=50) file = forms.FileField()
Để hiển thị thẻ element chọn file thì chúng ta dùng lớp FileField().
Tiếp theo chúng ta tạo thư mục templates
và file template:
<form action="" method="POST" enctype="multipart/form-data"> {% csrf_token %} <table> {{ form.as_table }} </table> <input type="submit" value="Submit" /> </form>
Để gửi file lên thì trong thẻ <form>
chúng ta phải khai báo thuộc tính enctype="multipart/form-data".
Sau khi đã có template và form để hiển thị thì chúng ta tiến hành tạo view để kết nối chúng với nhau.
from django.db import models # Create your models here. from django.http import HttpResponse from .forms import UploadFileForm def fileUploaderView(request): if request.method == 'POST': form = UploadFileForm(request.POST, request.FILES) if form.is_valid(): upload(request.FILES['file']) return HttpResponse("<h2>File uploaded successful!</h2>") else: return HttpResponse("<h2>File uploaded not successful!</h2>") form = UploadFileForm() return render(request, 'fileUploaderTemplate.html', {'form':form}) def upload(f): file = open(f.name, 'wb+') for chunk in f.chunks(): file.write(chunk)
Chúng ta viết hàm view fileUploaderView()
và hàm xử lý việc ghi file là upload().
if form.is_valid():
Phương thức is_valid()
có trong lớp django.forms.Form
sẽ kiểm tra tính hợp lệ của dữ liệu được gửi lên. Mục đích chính của lớp Form
trong Django chính là hỗ trợ chúng ta kiểm tra sự đúng đắn của dữ liệu được gửi lên. Chẳng hạn như khi bạn xây dựng chức năng up ảnh avatar thì bạn chỉ cho phép user gửi các file ảnh lên thôi, nhưng kẻ tấn công có thể gửi các file ảnh “giả” lên mà trình duyệt không biết, do đó khi dữ liệu được gửi tới server, chúng ta nên kiểm tra trước các dữ liệu này trước khi lưu vào hệ thống.
Ở đây phương thức is_valid()
chỉ có chức năng đơn giản là kiểm tra xem ô text title có dữ liệu hay không vì mặc định các field của Form
trong Django bắt buộc phải có dữ liệu mới được nhận.
upload(request.FILES['file']) return HttpResponse("<h2>File uploaded successful!</h2>")
Nếu dữ liệu là hợp lệ thì chúng ta tiến hành lưu file vào thư mục gốc của server và trả lời thông báo gửi thành công về cho người dùng.
def upload(f): file = open(f.name, 'wb+') for chunk in f.chunks(): file.write(chunk)
Hàm upload()
sẽ thực hiện copy file vào thư mục gốc của server (thư mục có file manage.py).
Cuối cùng chúng ta định nghĩa các url. Chúng ta sẽ tạo url trỏ tới hàm view trong app.
from django.conf.urls import url from . import views urlpatterns = [ url(r'^$', views.fileUploaderView), ]
Tiếp theo là url từ địa chỉ server tới app:
from django.conf.urls import url, include from django.contrib import admin urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^file-upload/', include('file_uploader.urls')) ]
Bây giờ chúng ta có thể chạy server và trỏ tới url localhost:8000/file-upload để thực hiện upload file.
File được upload thành công.
Thiết lập file
Khi Django server nhận file được gửi đến, trước khi lưu vào đĩa cứng thì dữ liệu của file được Django lưu vào đâu đó rồi mới thực sự được lưu trên đĩa.
Mặc định nếu kích thước file nhỏ hơn 2.5 MB thì Django sẽ lưu toàn bộ dữ liệu của file trong RAM, khi lưu vào đĩa thì Django chỉ cần đọc lại nội dung đó trong RAM rồi lưu vào đĩa thôi, do đó tốc độ lưu file rất nhanh.
Tuy nhiên nếu file tải lên quá lớn, Django sẽ lưu toàn bộ file này vào thư mục temp của hệ thống, trên Windows 7 thì thư mục này nằm tại địa chỉ C:\Users\<username>\AppData\Local\Temp rồi sau đó mới copy từ thư mục đó sang thư mục của server. Mà tốc độ đọc ghi với đĩa cứng lại chậm hơn RAM nên giả sử chúng ta có 2 file có dung lượng 2.4 và 2.5 MB thì thời gian up file có dung lượng 2.4 MB không khác gì file có dung lượng 2.5 MB, nhưng thời gian upload file có dung lượng 2.5 MB với file có dung lượng 2.6 MB lại khác nhau rất nhiều.
Tuy nhiên bạn có thể thiết lập lại một số thông tin cấu hình về file nhưng mình không đi sâu ở đây, nếu muốn bạn có thể xem thêm ở đây.