一、概述
在项目中,点击下载按钮,就可以下载文件。
传统的下载链接一般是get方式,这种链接是公开的,可以任意下载。
在实际项目,某些下载链接,是私密的。必须使用post方式,传递正确的参数,才能下载。
二、django项目
本环境使用django 3.1.5,新建项目download_demo
安装模块
1 | pip3 install djangorestframework django - cors - headers |
修改文件download_demo/settings.py
1 2 3 4 5 6 7 8 9 10 | 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 ] |
注册中间件
1 2 3 4 5 6 7 8 9 10 | 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 ] |
最后一行增加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # 跨域增加忽略 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
1 2 3 4 5 6 7 8 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | <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 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实现下载文件的资料请关注自学编程网其它相关文章!
- 本文固定链接: https://zxbcw.cn/post/207975/
- 转载请注明:必须在正文中标注并保留原文链接
- QQ群: PHP高手阵营官方总群(344148542)
- QQ群: Yii2.0开发(304864863)