1. 程式人生 > 程式設計 >vue+django實現下載檔案的示例

vue+django實現下載檔案的示例

一、概述

在專案中,點選下載按鈕,就可以下載檔案。

傳統的下載連結一般是get方式,這種連結是公開的,可以任意下載。

在實際專案,某些下載連結,是私密的。必須使用post方式,傳遞正確的引數,才能下載。

二、django專案

本環境使用django 3.1.5,新建專案download_demo

vue+django實現下載檔案的示例

安裝模組

pip3 install djangorestfhttp://www.cppcns.comramework django-cors-headers

修改檔案download_demo/settings.py

INSTALLED_APPS = [
 'django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','api.apps.ApiConfig','corsheaders',# 註冊應用cors
]

註冊中介軟體

MIDDLEWARE = [
 'django.middleware.security.SecurityMiddleware','django.contrib.sessions.middleware.SessionMiddleware','django.middleware.common.CommonMiddleware','django.middleware.csrf.CsrfViewMiddleware','django.contrib.auth.middleware.AuthenticationMiddleware','django.contrib.messages.middleware.MessageMiddleware','django.middleware.clic
程式設計客棧
kjacking.XFrameOptionsMiddleware','corsheaders.middleware.CorsMiddleware',# 註冊元件cors ]

最後一行增加

# 跨域增加忽略
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True

CORS_ALLOW_METHODS = (
 'GET','OPTIONS','PATCH','POST','VIEW',)

CORS_ALLOW_HEADERS = (
 'XMLHttpRequest','X_FILENAME','accept-encoding','authorization','content-type','dnt','origin','user-agent','x-csrftoken','x-requested-with','Pragma',)

修改download_demo/urls.py

from django.contrib import admin
from django.urls import path
from api import views

urlpatterns = [
 path('admin/',admin.site.urls),path('download/excel/',views.ExcelFileDownload.as_view()),]

修改api/views.py

from django.shortcuts import render,HttpResponse
from download_demo import settings
from django.utils.encoding import escape_uri_path
from django.http import StreamingHttpResponse
from django.http import jsonResponse
from rest_framework.views import APIView
from rest_framework import status
import os

class ExcelFileDownload(APIView):
 def post(self,request):
  print(request.data)
  # filename = "大江大河.xlsx"
  filename = request.data.get("filename")
  download_file_path = os.path.join(settings.BASE_DIR,"upload",filename)
  print("download_file_path",download_file_path)

  response = self.big_file_download(download_file_path,filename)
  if response:
   return response

  return JsonResponse({'status': 'HttpResponse','msg': 'Excel下載失敗'})

 def file_iterator(self,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

 def big_file_download(self,download_file_path,filename):
  try:
   response = StreamingHttpResponse(self.file_iterator(download_file_path))
   # 增加headers
   response['Content-Type'] = 'application/octet-stream'
   response['Access-Control-Expose-Headers'] = "Content-Disposition,Content-Type"
   response['Content-Disposition'] = "attachment; filename={}".format(escape_uri_path(filename))
   return response
  except Exception:
   return JsonResponse({'status': status.HTTP_400_BAD_REQUEST,'msg': 'Excel下載失敗'},status=status.HTTP_400_BAD_REQUEST)

在專案根目錄建立upload檔案

vue+django實現下載檔案的示例

裡面放一個excel檔案,比如:大江大河.xlsx

三、vue專案

新建一個vue專案,安裝ElementUI 模組即可。

新建test.vue

<template>
 <div style="width: 70%;margin-left: 30px;margin-top: 30px;">
 <el-button class="filter-item" type="success" icon="el-icon-download" @click="downFile()">下載</el-button>
 </div>
</template>

<script>
 import axios from 'axios'

 export default {
 data() {
  return {
  }
 },程式設計客棧mounted: function() {

 },methods: {
  downloadFile(url,options = {}){
  return new Promise((resolve,reject) => {
   // console.log(`${url} 請求資料,引數=>`,JSON.stringify(options))
   // axios.defaults.headers['content-type'] = 'application/json;charset=UTF-8'
   axios({
   method: 'post',url: url,// 請求地址
   data: options,// 引數
   responseType: 'blob' // 表明返回伺服器返回的資料型別
   }).then(
   response => {
    // console.log("下載響應",response)
    resolve(response.data)
    let blob = new Blob([response.data],{
    type: 'application/vnd.ms-excel'
    })
    // console.log(blob)
    // let fileName = Date.parse(new Date()) + '.xlsx'
    // 切割出檔名
    let fileNameEncode = response.headers['content-disposition'].split("filename=")[1];
    // 解碼
    let fileName = decodeURI程式設計客棧Component(fileNameEncode)
    // console.log("fileName",fileName)
    if (window.navigator.msSaveOrOpenBlob) {
    // console.log(2)
    navigator.msSaveBlob(blob,fileName)
    } else {
    // console.log(3)
    var link = document.createElement('a')
    link.h程式設計客棧ref = window.URL.createObjectURL(blob)
    link.download = fileName
    link.click()
    //釋放記憶體
    window.URL.revokeObjectURL(link.href)
    }
   },err => {
    reject(err)
   }
   )
  })
  },// 下載檔案
  downFile(){
  let postUrl= "http://127.0.0.1:8000/download/excel/"
  let params = {
   filename: "大江大河.xlsx",}
  // console.log("下載引數",params)
  this.downloadFile(postUrl,params)
  },}
 }
</script>

<style>
</style>

注意:這裡使用post請求,並將filename傳輸給api,用來下載指定的檔案。

訪問測試頁面,點選下載按鈕

vue+django實現下載檔案的示例

就會自動下載

vue+django實現下載檔案的示例

開啟工具欄,檢視響應資訊

vue+django實現下載檔案的示例

這裡,就是django返回的檔名,瀏覽器下載儲存的檔名,也是這個。

遇到中文,會進行URLcode編碼。

所以在vue程式碼中,對Content-Disposition做了切割,得到了檔名。

以上就是vue+django實現下載檔案的示例的詳細內容,更多關於vue+django實現下載檔案的資料請關注我們其它相關文章!