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)

View Code
在项目根目录创建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>

View Code
注意:这里使用post请求,并将filename传输给api,用来下载指定的文件。 

访问测试页面,点击下载按钮


 就会自动下载


打开工具栏,查看响应信息


这里,就是django返回的文件名,浏览器下载保存的文件名,也是这个。

遇到中文,会进行URLcode编码。

所以在vue代码中,对Content-Disposition做了切割,得到了文件名。
————————————————
版权声明:本文为CSDN博主「shykevin」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/shykevin/article/details/113869015

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue是一种流行的JavaScript框架,用于构建用户界面。Django是一个用于构建Web应用程序的Python框架。使用这两种框架可以很容易地实现文件下载的功能。 首先,在Django中,你需要创建一个视图函数来处理文件下载的请求。你可以使用Python的内置模块`open`来打开文件,并将其内容发送给浏览器。具体代码如下: ```python from django.http import FileResponse import os def download_file(request): file_path = '/path/to/your/file.pdf' # 文件路径 file_name = os.path.basename(file_path) # 获取文件名 response = FileResponse(open(file_path, 'rb'), as_attachment=True) response['Content-Disposition'] = f'attachment; filename="{file_name}"' return response ``` 在Vue中,你可以创建一个按钮或链接来触发文件下载的请求。使用`axios`库来发起HTTP请求并下载文件。具体代码如下: ```javascript <template> <div> <button @click="downloadFile">下载文件</button> </div> </template> <script> import axios from 'axios'; export default { methods: { downloadFile() { axios({ url: 'http://your-api-url/download', method: 'GET', responseType: 'blob', // 必须设置为blob }).then(response => { const url = window.URL.createObjectURL(new Blob([response.data])); const link = document.createElement('a'); link.href = url; link.setAttribute('download', 'file.pdf'); // 设置下载文件文件名 document.body.appendChild(link); link.click(); }); } } } </script> ``` 以上是一个简单的示例,演示了如何在VueDjango实现文件下载的功能。当用户点击“下载文件”按钮时,Vue将发送一个HTTP请求到Django后端,后端会返回文件的内容,然后前端利用Blob对象创建一个URL,最终通过创建一个a标签实现文件下载
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值