这篇文章主要介绍了vue+django实现下载文件的示例,帮助大家更好的理解和学习使用vue框架,感兴趣的朋友可以了解下
正文
vue+django实现下载文件的示例
一、概述
在项目中,点击下载按钮,就可以下载文件。
传统的下载链接一般是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实现下载文件的资料请关注米米素材网其它相关文章!
原文链接:https://cloud.tencent.com/developer/article/1797607

发表评论