1. 程式人生 > >django 實現檔案下載功能

django 實現檔案下載功能

一、概述

在實際的專案中很多時候需要用到下載功能,如導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
View Code

 

程式碼解釋:

index是預設的首頁展示

file_down 是用來做下載的。

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

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

 

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

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

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

 

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

 

啟動專案,訪問首頁:

這裡使用的是edge瀏覽器

 

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

點選開啟

 

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