一、概述
在项目中,点击下载按钮,就可以下载文件。
传统的下载链接一般是get方式,这种链接是公开的,可以任意下载。
在实际项目,某些下载链接,是私密的。必须使用post方式,传递正确的参数,才能下载。
二、django项目
本环境使用django 3.1.5,新建项目download_demo
安装模块
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文件
里面放一个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,用来下载指定的文件。
访问测试页面,点击下载按钮
就会自动下载
打开工具栏,查看响应信息
这里,就是django返回的文件名,浏览器下载保存的文件名,也是这个。
遇到中文,会进行URLcode编码。
所以在vue代码中,对Content-Disposition做了切割,得到了文件名。
以上就是vue+django实现下载文件的示例的详细内容,更多关于vue+django实现下载文件的资料请关注其它相关文章!
© 版权声明
THE END
暂无评论内容