django 實現文件下載功能

  • 2020 年 2 月 18 日
  • 筆記

一、概述

在實際的項目中很多時候需要用到下載功能,如導excel、pdf或者文件下載,當然你可以使用web服務自己搭建可以用於下載的資源伺服器,如nginx,這裡我們主要介紹django中的文件下載。

前端實現方式

a標籤+響應頭資訊

<a href="/download/1/">下載圖片</a>

注意:這裡的1指的是MySQL表的主鍵id

後端實現方式

使用django有三種文件下載方式,分別是HttpResponse,StreamingHttpResponse,FileResponse

詳情,請參考鏈接

https://www.jb51.net/article/137790.htm

本文主要介紹StreamingHttpResponse實現方式

二、實際操作

新建項目

新建一個Django項目untitled1,這裡的是Django 2.x版本。

目錄結構如下:

./  ├── app  │   ├── admin.py  │   ├── apps.py  │   ├── __init__.py  │   ├── migrations  │   │   └── __init__.py  │   ├── models.py  │   ├── tests.py  │   └── views.py  ├── manage.py  ├── templates  │   └── index.html  ├── untitled1  │   ├── __init__.py  │   ├── settings.py  │   ├── urls.py  │   └── wsgi.py  └── upload      └── images          └── animation.jpg

默認創建了一個應用,名叫app

upload是用來存放上傳的圖片

簡單示例

這裡以一個簡單的頁面,來介紹如何實現下載功能!

修改urls.py,增加路由。

注意:紅色部分,是需要修改的

from django.contrib import admin  from django.urls import path,re_path  from app import views    urlpatterns = [      path('admin/', admin.site.urls),      path('', views.index),      re_path('download/(?P<id>d+)', views.file_down,name = "download"),  ]

修改views.py,增加視圖函數

from django.shortcuts import render, HttpResponse  from django.http import StreamingHttpResponse  import os    def index(request):      return render(request,"index.html")    # Create your views here.  def file_down(request, id):      """      下載壓縮文件      :param request:      :param id: 資料庫id      :return:      """      data = [{"id":"1","image":"animation.jpg"}]  # 模擬mysql表數據      file_name = ""  # 文件名      for i in data:          if i["id"] == id:  # 判斷id一致時              file_name = i["image"]  # 覆蓋變數            base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))  # 項目根目錄      file_path = os.path.join(base_dir, 'upload','images', file_name)  # 下載文件的絕對路徑        if not os.path.isfile(file_path):  # 判斷下載文件是否存在          return HttpResponse("Sorry but Not Found the File")        def file_iterator(file_path, chunk_size=512):          """          文件生成器,防止文件過大,導致記憶體溢出          :param file_path: 文件絕對路徑          :param chunk_size: 塊大小          :return: 生成器          """          with open(file_path, mode='rb') as f:              while True:                  c = f.read(chunk_size)                  if c:                      yield c                  else:                      break        try:          # 設置響應頭          # StreamingHttpResponse將文件內容進行流式傳輸,數據量大可以用這個方法          response = StreamingHttpResponse(file_iterator(file_path))          # 以流的形式下載文件,這樣可以實現任意格式的文件下載          response['Content-Type'] = 'application/octet-stream'          # Content-Disposition就是當用戶想把請求所得的內容存為一個文件的時候提供一個默認的文件名          response['Content-Disposition'] = 'attachment;filename="{}"'.format(file_name)      except:          return HttpResponse("Sorry but Not Found the File")        return response

程式碼解釋:

index是默認的首頁展示

file_down 是用來做下載的。

為了簡單實現,在file_down 中的data,表示資料庫中的記錄。需要指定id才能對應的文件!

其他程式碼,有詳細的注釋,這裡就不多介紹了

修改index.html,注意:這裡需要指定id。這裡僅做示例,固定了id。

實際情況應該查詢資料庫,使用Django模板引擎來渲染的

<!DOCTYPE html>  <html>  <head>      <meta charset="UTF-8">      <title>Title</title>  </head>  <body>  <a href="/download/1/">下載圖片</a>  </body>  </html>

upload目錄是用來存放上傳文件的。在images裡面我放了一張動漫圖片!

啟動項目,訪問首頁:

這裡使用的是edge瀏覽器

點擊下載圖片,瀏覽器底部會有提示

點擊打開

就會打開圖片,效果如下: