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实现下载文件的资料请关注其它相关文章!

以上是 vue+django实现下载文件的示例 的全部内容, 来源链接: www.h5w3.com/238987.html

回到顶部