百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

django+vue+axios+buefy实现上传文件进度条功能

bigegpt 2024-09-20 13:54 6 浏览

web开发,上传下载文件是一个非常普遍的需求,但这一块牵扯到文件的存储、命名等,有很多知识点需要我们去掌握和练习!

最近帮一个客户定制一个校园类的OA系统,功能主要集中在微信端,也就是对接的微信公众号的一个项目,这个项目的后端我用了django框架来完成,当然,使用django框架是客户的要求,同时也是我比较熟悉的一个框架。

客户的要求是要在微信客户端内能上传文件以及压缩包,其实我个人感觉移动端上传图片的需求比较常见,但上传文件及压缩包这个功能并不常见,可以说就是个鸡肋,我不知道谁会在手机端压缩好文件进行上传,其次即使上传word一类的文件,应该在电脑端编辑好上传比较方便,如果再回到微信端去上传,我估计用户会骂娘。

不知道客户这奇葩需求是怎么考虑的,但作为开发的我们又有什么办法,为了钱,只能满足了。

这里插一句,不知道各位开发大佬在开发过程中有没有遇到哪些奇葩需求,可以吐槽吐槽!

好了,言归正传,实现需求我们是认真的,我这里前端使用了vue+axios+buefy来完成,vue和axios不过多解释,一对前端好搭档,buefy是一个非常简单但很好用的vue2 ui组件库,我个人非常喜欢,不但可以npm安装使用,并且还可以直接引入到html中,简单轻量,上手容易,郑重推荐给大家!

django的后端接口

首先来看一下我的后端接口代码

class AddTaskFileView(View):
    # 收文件接口
    def post(self, request, *args, **kwargs):
        user_id = request.POST.get('user_id')
        school_task_id = request.POST.get('school_task_id')
        # 必须使用request.FILES接收文件
        file_path = request.FILES.get('file_path')
        new_file_name = request.POST.get('new_name')
        print(new_file_name)
        
        school_task = SchoolTask.objects.get(id=int(school_task_id))
        user = User.objects.get(id=int(user_id))
        
        if not file_path:
            return JsonResponse({'code': 'err', 'message': '请选择有效的文件上传!'})
        
        # 处理文件名称
        ## 这里有个自定义文件名称的功能
        ## 如果传了自定义名称就是用自定义,负责使用默认构造的文件名称
        file_name_list = file_path.name.split('.')
        if new_file_name:
            file_path.name = f'{new_file_name}.{file_name_list[-1]}'
        else:
            print(user.code, user.name)
            if user.code and user.name and user.student_team:
                file_path.name = f'{user.student_team.name}{user.code}{user.nickname}.{file_name_list[-1]}'   
        
        # 保存文件
        RootIncludeFile.objects.create(school_task=school_task, student_owner=user, student_file=file_path)
        # 转到已上传
        hav_read = RootStudentHaveRead()
        hav_read.school_task = school_task
        hav_read.read_owner = user
        hav_read.is_read = True
        hav_read.save()
        return JsonResponse({'code': 'ok', 'message': '上传成功,即将跳转至已完成列表页!'})

这个后端接口非常简单,很容易就能看懂,我在这里稍微解释一下几个比较特殊的地方,django后端接收文件数据必须使用request.FILES,这个大家一定要注意,否则获取不到数据。这里有一个特殊的需求就是,后端可以控制是否允许用户自定义文件名称,我这里做了处理,如果用户传过来的数据中,自定义名称存在,那么就是用自定义名称,否则就使用默认构造的名称,这一块就牵扯到前后端沟通的一个问题,自定义文件名称的表单何时出现交由前端处理!后端只是传递给配置数据!【这里我就不存在,因为我一人全干!】

再来看保存文件这里,我这里使用了一个模型专门保存用户上传的数据,这是因为除了保存文件还有一些和文件相关的信息需要保存并且获取,基于这个需求我们选择了使用模型来保存文件,当然,你也可以自己写保存文件的方法在这里替换即可!

前端处理

这里简单说一下,为什么要做这个进度条的功能,因为在异步提交文件的过程中,如果任何提示都没有,就会给用户造成一种我是不是上传按钮没点击上的错觉,造成重复提交多次,用户体验不好的同时,也有可能造成系统崩溃,尤其上传大文件!

前端主要代码

  • 前端主要显示代码
<h1 class=" has-text-black has-text-weight-bold is-size-5 mb-3">提交文件</h1>
<!-- 进度条 默认隐藏-->
<b-progress 
  type="is-success" 
  :value=num 
  show-value
  format="percent"
  v-show="pShow"
></b-progress>

<!-- 选择文件表单 -->
<template>
  <b-field class="file" v-show="isShow">
    <b-upload v-model="file"  expanded>
      <a class="button is-primary is-fullwidth">
        <b-icon icon="upload"></b-icon>
        <span>[[  file.name || "请选择文件" ]]</span>
      </a>
    </b-upload>
  </b-field>
</template>

<!-- 是否允许自定义文件名表单 -->
{% if not_task.is_file_name %}
<b-field label="自定义文件名:">
  <b-input v-model="new_name"></b-input>
</b-field>
{% endif %}

<!-- 点击上传按钮  绑定点击上传事件 addTaskFile -->
<b-button 
  type="is-success" 
  expanded
  :disabled="dis"
  @click="addTaskFile">
  [[ btText ]]
</b-button>
  • 前端vue相关处理方法及数据

我这里前端处理的思路可作为参考,当用户选择上传文件后,方可点击上传按钮,当用户点击上传按钮后,按钮置灰不可点击,按钮的文件变为“文件正在上传中...”,进度条出现,默认是隐藏的,上传完成后,等待1s,将按钮文字变为成功提示,并弹出成功提示消息,跳转到指定页面;否则,提示上传失败,刷新上传页面,提示重新上传!当然失败哪里也可以做不刷新处理,因为我们有Vue可以很方便的无刷新修改数据!【主要是因为我懒,没做!】

<script>
    var school_task_id = '{{ not_task.id }}';
    var user_id = '{{ request.user.id }}';
    var NotTask = new Vue({
        el: '#NotTask',
        delimiters: ['[[', ']]'],
        data: {
            file: {},
            new_name: '',
            num:0,
            dis: false,
            btText: '点击上传',
            isShow:true,
            pShow:false,
            isRedic: false
        },
        methods: {
            addTaskFile(){
                // 声明this
                let self = this;
                console.log('上传文件', this.file.path)
                let sendData = new FormData();
                sendData.append('file_path', self.file);
                sendData.append('school_task_id', school_task_id);
                sendData.append('user_id', user_id);
                sendData.append('new_name', self.new_name);
                axios({
                    url: '/h5/users/add_task/file/',
                    method: 'post',
                    data: sendData,
                    // 上传文件处理
                    onUploadProgress(progressEvent) {
                        if (progressEvent.lengthComputable) {
                            // 计算文件上传进度
                            let val = (progressEvent.loaded / progressEvent.total * 100).toFixed(0);
                            self.pShow = true
                            self.isShow = false
                            self.btText = "正在上传 "
                            self.dis = true
                            // 将进度数据赋值给进度条
                            self.num = parseInt(val)
                            // 通过判断进度到100后,代表完成,将允许跳转数据设置为true
                            if (self.num == 100) {
                                self.isRedic = true
                            } 
                            
                        }
                    },
                }).then(res => {
                    console.log(res)
                    if (self.isRedic){
                        // setTimeout(())
                        setTimeout(() => {
                            self.btText = "上传成功"
                            self.$buefy.toast.open({
                                message:  "上传成功",
                                type: 'is-success'
                            });
                            setTimeout(() => {
                                window.location.replace("/h5/owner/yes/task/")
                            }, 1000)
                        }, 1000)
                    }else{
                        this.$buefy.toast.open({
                            message: "上传失败,请重新上传!",
                            type: 'is-danger'
                        });
                        window.location.reload()
                    }
                })
            }
        }
    })
</script>

前端这里有几个重要的点需要注意

  1. 构造数据传递的方法包含文件一定要使用new FormData();
  2. vue2中关于this的指向一定要有了解,必须在上传方法开始通过一个变量声明this
  3. axios的上传文件数据获取不在then的回调中,而在config中,也就是在与url同级的数据结构中
onUploadProgress(progressEvent) {
  if (progressEvent.lengthComputable) {
    // 计算文件上传进度
     let val = (progressEvent.loaded / progressEvent.total * 100).toFixed(0);
     ...
       // 将进度数据赋值给进度条
       self.num = parseInt(val)
       console.log(parseInt(val))
      ...
  }
},

这段代码是axios获取文件数据的核心,记住他,使用axios上传文件搭配任何UI框架你都能处理进度条的功能,至于他是如何实现的,可以去看看axios的代码和说明,其实内部并不复杂,相比Ajax可以说有点简陋。

到这里我们的上传文件进度条的功能就完成了,看下演示动图吧!

欢迎大家关注学习,一起进步,笔者专注django相关开发,对django有深入研究,可一起学习探讨,并且承接django相关项目的开发任务!

相关推荐

方差分析简介(方差分析通俗理解)

介绍方差分析(ANOVA,AnalysisofVariance)是一种广泛使用的统计方法,用于比较两个或多个组之间的均值。单因素方差分析是方差分析的一种变体,旨在检测三个或更多分类组的均值是否存在...

正如404页面所预示,猴子正成为断网元凶--吧嗒吧嗒真好吃

吧嗒吧嗒,绘图:MakiNaro你可以通过加热、冰冻、水淹、模塑、甚至压溃压力来使网络光缆硬化。但用猴子显然是不行的。光缆那新挤压成型的塑料外皮太尼玛诱人了,无法阻挡一场试吃盛宴的举行。印度政府正...

Python数据可视化:箱线图多种库画法

概念箱线图通过数据的四分位数来展示数据的分布情况。例如:数据的中心位置,数据间的离散程度,是否有异常值等。把数据从小到大进行排列并等分成四份,第一分位数(Q1),第二分位数(Q2)和第三分位数(Q3)...

多组独立(完全随机设计)样本秩和检验的SPSS操作教程及结果解读

作者/风仕在上一期,我们已经讲完了两组独立样本秩和检验的SPSS操作教程及结果解读,这期开始讲多组独立样本秩和检验,我们主要从多组独立样本秩和检验介绍、两组独立样本秩和检验使用条件及案例的SPSS操作...

方差分析 in R语言 and Excel(方差分析r语言例题)

今天来写一篇实际中比较实用的分析方法,方差分析。通过方差分析,我们可以确定组别之间的差异是否超出了由于随机因素引起的差异范围。方差分析分为单因素方差分析和多因素方差分析,这一篇先介绍一下单因素方差分析...

可视化:前端数据可视化插件大盘点 图表/图谱/地图/关系图

前端数据可视化插件大盘点图表/图谱/地图/关系图全有在大数据时代,很多时候我们需要在网页中显示数据统计报表,从而能很直观地了解数据的走向,开发人员很多时候需要使用图表来表现一些数据。随着Web技术的...

matplotlib 必知的 15 个图(matplotlib各种图)

施工专题,我已完成20篇,施工系列几乎覆盖Python完整技术栈,目标只总结实践中最实用的东西,直击问题本质,快速帮助读者们入门和进阶:1我的施工计划2数字专题3字符串专题4列表专题5流程控制专题6编...

R ggplot2常用图表绘制指南(ggplot2绘制折线图)

ggplot2是R语言中强大的数据可视化包,基于“图形语法”(GrammarofGraphics),通过分层方式构建图表。以下是常用图表命令的详细指南,涵盖基本语法、常见图表类型及示例,适合...

Python数据可视化:从Pandas基础到Seaborn高级应用

数据可视化是数据分析中不可或缺的一环,它能帮助我们直观理解数据模式和趋势。本文将全面介绍Python中最常用的三种可视化方法。Pandas内置绘图功能Pandas基于Matplotlib提供了简洁的绘...

Python 数据可视化常用命令备忘录

本文提供了一个全面的Python数据可视化备忘单,适用于探索性数据分析(EDA)。该备忘单涵盖了单变量分析、双变量分析、多变量分析、时间序列分析、文本数据分析、可视化定制以及保存与显示等内容。所...

统计图的种类(统计图的种类及特点图片)

统计图是利用几何图形或具体事物的形象和地图等形式来表现社会经济现象数量特征和数量关系的图形。以下是几种常见的统计图类型及其适用场景:1.条形图(BarChart)条形图是用矩形条的高度或长度来表示...

实测,大模型谁更懂数据可视化?(数据可视化和可视化分析的主要模型)

大家好,我是Ai学习的老章看论文时,经常看到漂亮的图表,很多不知道是用什么工具绘制的,或者很想复刻类似图表。实测,大模型LaTeX公式识别,出乎预料前文,我用Kimi、Qwen-3-235B...

通过AI提示词让Deepseek快速生成各种类型的图表制作

在数据分析和可视化领域,图表是传达信息的重要工具。然而,传统图表制作往往需要专业的软件和一定的技术知识。本文将介绍如何通过AI提示词,利用Deepseek快速生成各种类型的图表,包括柱状图、折线图、饼...

数据可视化:解析箱线图(box plot)

箱线图/盒须图(boxplot)是数据分布的图形表示,由五个摘要组成:最小值、第一四分位数(25th百分位数)、中位数、第三四分位数(75th百分位数)和最大值。箱子代表四分位距(IQR)。IQR是...

[seaborn] seaborn学习笔记1-箱形图Boxplot

1箱形图Boxplot(代码下载)Boxplot可能是最常见的图形类型之一。它能够很好表示数据中的分布规律。箱型图方框的末尾显示了上下四分位数。极线显示最高和最低值,不包括异常值。seaborn中...