vue+django实现下载文件的示例

一、概述

在项目中,点击下载按钮,就可以下载文件。

传统的下载链接一般是get方式,这种链接是公开的,可以任意下载。

在实际项目,某些下载链接,是私密的。必须使用post方式,传递正确的参数,才能下载。

二、django项目

本环境使用django 3.1.5,新建项目download_demo

vue+django实现下载文件的示例

安装模块

pip3 install djangorestframework 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.clickjacking.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 = decodeURIComponent(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.href = 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实现下载文件的资料请关注其它相关文章!

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容