Django – Upload file

5/5 - (10 votes)

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.

Untitled

File được upload thành công.

Untitled

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 serverMà 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.

4 1 vote
Article Rating
Subscribe
Thông báo cho tôi qua email khi
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

6 Comments
Inline Feedbacks
View all comments
Đức PhạmTrung
Đức PhạmTrung
7 năm trước

Anh ơi em em thắc mắc chút là khi mà mình up 1 file khác, ví dụ như file excel, XML, Pdf thì làm sao đọc được nó để mình có thể view đc trên browser ạ. Ví dụ như là file Pdf thì có thể up file lên rồi có thể đọc file đó qua 1 cửa sổ windown khác được không ấy ạ.
Cảm ơn anh nhiều 🙂

Đức PhạmTrung
Đức PhạmTrung
7 năm trước
Reply to  Phở Code

Thanks anh ?

hoàng
7 năm trước

giờ mình có file html, css sẵn rồi trên web tĩnh giờ mình kết nối với Django sao vậy?

anh
anh
2 năm trước

ad cho mình hỏi, ví dụ mình muốn upload file lên folder mình vừa tạo ngay khi nhận request từ client trước khi upload file lên thì làm thế nào ạ, folder này vẫn nằm trong media nha