Django2.X—文件下載功能

文件下載功能

響應內容除了返回網頁信息外,還可以實現文件下載功能,是網站常用的功能之一。Django提供三種方式實現文件下載功能,分別是HttpResponse、StreamingHttpResponse和FileResponse,三者說明如下:

  • HttpResponse是所有響應過程的核心類,它的底層功能類是HttpResponseBase.
  • StreamingHttpResponse是在HttpResponseBase的基礎上進行繼承與重寫的,它實現流式響應輸出(流式響應輸出是使用Python的迭代器將數據進行分段處理並傳輸的),適用於大規模數據響應和文件傳輸響應。
  • FileResponse是在StreamingHttpResponse的基礎上進行繼承與重寫的,它實現文件的流式響應輸出,只適用於文件傳輸響應。

以MyDjango爲例,在MyDjango的urls.py、index的urls.py、view.py和templates的index.html中分別定義路由、視圖函數和模板文件,代碼如下:

# MyDjango的urls.py
from django.urls import path, include
urlpatterns = [
    # 指向index的路由文件urls.py
    path('', include(('index.urls', 'index'), namespace='index')),
]

# index的urls.py
from django.urls import path
from . import views

urlpatterns = [
    # 定義首頁的路由
    path('', views.index, name='index'),
    path('download/file1', views.download1, name='download1'),
    path('download/file2', views.download2, name='download2'),
    path('download/file3', views.download3, name='download3'),
]

# index的views.py
from django.shortcuts import render
from django.http import HttpResponse, Http404
from django.http import StreamingHttpResponse
from django.http import FileResponse

def index(request):
    return render(request, 'index.html')

def download1(request):
    file_path = 'D:\cat.jpg'
    try:
        r = HttpResponse(open(file_path, 'rb'))
        r['content_type'] = 'application/octet-stream'
        r['Content-Disposition'] = 'attachment; filename=cat.jpg'
        return r
    except Exception:
        raise Http404('Download error')

def download2(request):
    file_path = 'D:\duck.jpg'
    try:
        r = StreamingHttpResponse(open(file_path, 'rb'))
        r['content_type'] = 'application/octet-stream'
        r['Content-Disposition'] = 'attachment; filename=duck.jpg'
        return r
    except Exception:
        raise Http404('Download error')

def download3(request):
    file_path = 'D:\dog.jpg'
    try:
        f = open(file_path, 'rb')
        r = FileResponse(f, as_attachment=True, filename='dog.jpg')
        return r
    except Exception:
        raise Http404('Download error')
        
# templates的index.html
<!DOCTYPE html>
<html>
<body>
<a href="{% url 'index:download1' %}">HttpResponse-下載</a>
<br>
<a href="{% url 'index:download2' %}">StreamingHttpResponse-下載</a>
<br>
<a href="{% url 'index:download3' %}">FileResponse-下載</a>
</body>
</html>

上述代碼是整個MyDjango項目的功能代碼,文件下載功能實現原理如下:

  • MyDjango的urls.py定義的路由指向index的urls.py文件。
  • index的urls.py定義4條路由信息,路由index是網站事業,路由所對應的視圖函數index將模板文件index.html作爲網頁內容呈現在瀏覽器上。
  • 當在瀏覽器訪問127.0.0.1:8000時,網頁會出現3條地址鏈接,每條地址鏈接分別對應路由download1、download2和downloads3,這些路由所對應的視圖函數分別使用不同的響應類實現文件下載功能。
  • 視圖函數download1使用HttpResponse實現文件下載傳入響應類HttpResponse進行實例化,並對實例化對象r設置參數content_type和Content-Disposition,這樣就能實現文件下載功能。
  • 視圖函數download2使用StrieamingHttpResponses實現文件下載,該類的使用方式與響應類HttpResponse的使用方式相同。
  • 視圖函數download3使用FileResponse實現文件下載,該類的使用方式最爲簡單,只需將文件以字節流的方式讀取並且設置參數as_attachment和filename,然後將三者一併傳入FileResponse進行實例化即可。

上述例子說明三者之間存在一定差異,說明如下:

  • HttpResponse實現文件下載存在很大弊端,其工作原理是將文件讀取並載入內存,然後輸出到瀏覽器上實現下載功能。如果下載的文件較大,該方法就會佔用很多內存。對於下載文件,Django推薦使用StreamingHttpResponse和FileResponse方法,這兩個方法將下載文件分批寫入服務器的本地磁盤,而不再將文件載入服務器的內存。
  • StreamingHttpResponse和FileResponse的實現原理是相同的,兩者都是將下載文件分批寫入本地磁盤,實現文件的流式響應輸出。
  • 從適用範圍來說,StreamingHttpResponse的適用範圍更爲廣泛,可支持大規模數據或文件輸出,而FileResponse只支持文件輸出。
  • 從使用方式來說,由於StreamingHttpResponse支持數據或文件輸出,因此在使用時需要設置響應輸出類型和方式,而FileResponse只需設置3個參數即可實現文件下載功能。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章