vue3 + axios 实现带进度条的下载对话框

news2025/2/24 12:26:17

文章目录

    • 问题
    • 实现
      • 采用axios实现下载请求
      • 写一个进度下载对话框
      • 调用对话框
    • 参考链接

问题

上传下载是前端经常面临的两大需求,当文件比较大时,下载进度显示能提升用户体验。本文结合vue3介绍下载对话框的实现。当点击页面中下载按钮后,会呈现类似下面效果的对话框:
在这里插入图片描述
下载进度达到100%时,点击保存按钮即可保存文件。

主要原理:axios下载文件时,文件数据作为blob对象先放到内存中,然后可以对这个blob对象做各种操作。

实现

采用axios实现下载请求

进度显示主要利用了axios的onProgress()重载方法。

import Axios, { AxiosInstance, AxiosRequestConfig, ResponseType } from "axios";

const downloadConfig: AxiosRequestConfig = {
  baseURL,
  timeout: 100000,
  responseType: "blob",
  headers: {
    'Content-Type': 'application/octet-stream'
  }
}

private static axiosInstance: AxiosInstance = Axios.create(defaultConfig);
private static axiosDownloadInstance: AxiosInstance = Axios.create(downloadConfig);

public download<T, P>(url: string, filename: string, onProgress: DownloadProgress, onCompleted: DownloadCompleted): Promise<P> {    
    const config = {
      method: 'get',
      onDownloadProgress: (evt)=>onProgress(evt.loaded, evt.total),
      url
    } as PureHttpRequestConfig;
    return new Promise((resolve, reject) => {
      PureHttp.axiosDownloadInstance
        .request(config)
        .then((response: any) => {
          onCompleted(response.data);          
          resolve(response);
        })
        .catch(error => {
          reject(error);
        });
    });
  }

写一个进度下载对话框

download_dialog.vue的实现:

<template>
  <el-dialog v-model="visible" :title="title" :append-to-body=true width="50%">
    <el-progress :text-inside="true" :stroke-width="26" :percentage="percent" />
    <template #footer>
        <span>
          <el-button type="primary" @click="cancel()">取消</el-button>
          <el-button :type="type" @click="doSave()" :disabled="disabled">保存</el-button>
        </span>
    </template>
  </el-dialog>
</template>
<script lang="ts" setup>
import {ref, shallowRef, watch, onMounted, getCurrentInstance} from "vue"
import {ElDialog, ElForm, ElFormItem, ElInput, ElButton, ElProgress} from "element-plus";
import {closeDialog} from "/@/components/dialog"
import { http } from "/@/utils/http";

const props = defineProps<{downloadUrl:string, filename: string}>()
const visible = ref<boolean>(true)
const type = ref('info')
const disabled = ref<boolean>(true)
const title = ref(`${props.filename}》下载`)

const percent = ref<number>(0)
const blobData = ref()

onMounted(() => {
  http.download(props.downloadUrl, props.filename, onProgress, onCompleted)
})

const onProgress = (loaded, total) => {      
  percent.value = parseInt(loaded * 100 / total)
  if (percent.value == 100) {    
    disabled.value = false
    type.value = 'success'
  }
}

const onCompleted = (blob) => {  
  blobData.value = blob
}

const cancel = () => {  
  visible.value = false
}

const doSave = () => {         
  var urlObject = window.URL || window.webkitURL || window
  const url = urlObject.createObjectURL(
    new Blob([blobData.value], {
      type: 'application/octet-stream',
    })
  );    

  let saveLink = document.createElement('a')
  saveLink.href = url
  saveLink.download = props.filename + '.pdf'
  saveLink.click()

  URL.revokeObjectURL(url);
  visible.value = false
}



</script>


调用对话框

利用vue3的h()和render()函数绘制对话框:

import {Component, h, render, shallowRef} from "vue";
import DownloadDialog from "./download_dialog.vue"

/**
 * 开启一个下载对话框
 * @param downloadUrl :下载文件的链接
 * @param filename :保存文件的名称
 * @returns 
 */
export function openDownloadDialog(downloadUrl, filename) {
    const vnode = h(DownloadDialog, {downloadUrl, filename})
    vnode.appContext = null
    const container = document.createElement('div')
    render(vnode, container)
    const instance = vnode.component
    const vm = instance.proxy
    return vm
}

测试:

const downloadPDF = async (bookId, bookName) => {
  openDownloadDialog("/api/ebook/download/pdf/" + bookId, bookName)  
}

参考链接

  • https://muhimasri.com/blogs/how-to-save-files-in-javascript/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/743627.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在日常学习生活中,究竟该如何保持稳定的情绪呢?

方向一&#xff1a;分享工作中让你有强烈情绪波动的事情 编程仅仅是工程的过程实践化&#xff0c;投入进去确实会出现精神集中&#xff0c;出现问题排查过程会绞尽脑汁&#xff0c;甚至抓耳挠腮&#xff0c;当发现问题无法解决时不如放下来想一想&#xff0c;是不是知识点掌握不…

按日,周,年统计,无的数据补充0

需求&#xff1a;按日-周-年统计。统计涉及到3张表数据。 写sql。先把3张表数据摘取出来&#xff0c;只需对3张表的时间做分组统计即可。 按日统计 select DAY(dateff) as time,IFNULL(count(id),0)as num from(select create_time as dateff,id as id from cz_taxi_orders…

go语言开发 三种容器类型:数组、切片、map

目录 go语言中的三种容器类型&#xff1a;数组&#xff0c;切片&#xff0c;map go 与 python的容器类型对比 python go&#xff1a; 数组&#xff1a; 数组的定义&#xff1a;&#xff08;定义数组的格式、二维数组、初始化、任意长度初始化、取值&#xff09; 数组的…

swager异常_Failed to load API definition.

现象 Fetch error Internal Server Error /swagger/base/swagger.json 排查 按照以往的经历基本都是因为Conroller中的类中有非对外调用的函数&#xff0c;但是用了public修饰函数&#xff0c;会导致这个问题。这个问题通常通过查看git/svn中最近的提交记录&#xff0c;找出…

hadoop -Unable to start failover controller. Parent znode does not exist

Unable to start failover controller. Parent znode does not exist 问题描述 今天使用星环的TDH集群时&#xff0c;HDFS服务宕掉&#xff0c;在后台查看namenode 始终起不来 kubectl get pod -o wide | grep hdfs 如上图&#xff0c;k8s pod 起来又crash 掉&#xff0c;然后…

10 thymeleaf模版引擎使用

10.1 原理 首先&#xff0c;在idea搜索thymeleafProperties这个配置类。 通过源代码可以发现&#xff0c;使用的文件后缀是html&#xff0c;文件应该放在templates路径下&#xff1a; 10.1 依赖 直接加入启动器的thymeleaf依赖。 <dependency><groupId>org.sprin…

814. 复制数组

链接&#xff1a; 链接 题目&#xff1a; 给定两个数组 aa 和 bb 以及一个整数 sizesize&#xff0c;请你编写一个函数&#xff0c;void copy(int a[], int b[], int size)&#xff0c;将 aa 数组中的前 sizesize 个数字&#xff0c;复制到 bb 数组中。 复制完成后&#xff0c;…

AR 技术应用与管理:施工建造、机柜扫描、办公室导航

随着科技的不断革新和创新&#xff0c;越来越多的行业开始迎来数字化时代的变革。建筑行业作为人类历史上最重要的产业之一&#xff0c;在数字化转型方面同样也在不断推进。图扑软件结合 AR 技术的应用&#xff0c;为建筑行业带来了更加便捷高效的建筑施工过程管理。 传统的建…

娇滴滴的一朵花(Python实现)

目录 1 娇滴滴的她 2 Python代码实现 1 娇滴滴的她 娇滴滴。双眉敛破春山色。春山色。 为君含笑,为君愁蹙。多情别後无消息。 此时更有谁知得。谁知得。夜深无寐&#xff0c;度江横笛。 2 Python代码实现 import turtle from turtle import * turtle.title(春天送她一朵小花) #…

cf卡中毒了?别担心,这2种方法帮助你恢复数据

在现代数字化生活中&#xff0c;数据的重要性日益突出&#xff0c;而CF卡作为一种常见的存储设备&#xff0c;其安全性问题也备受关注。然而&#xff0c;由于各种原因&#xff0c;包括但不限于操作失误、设备故障和病毒攻击&#xff0c;我们可能会遇到数据丢失的情况。在这篇文…

OSS-Fuzz----OSS-Fuzz简介

【原文链接】OSS-Fuzz----OSS-Fuzz简介 一、OSS-Fuzz 简介 OSS-Fuzz是由Google开发和维护的一个开源项目&#xff0c;旨在帮助开发者改善软件的安全性和稳定性。它是一个自动化的模糊测试工具&#xff0c;可以在大规模的测试环境中发现软件中的漏洞和错误。 OSS-Fuzz使用模糊…

基于SpringBoot+vue的体质测试数据分析及可视化设计与实现

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

go-zero系列:接入Prometheus

参考文档&#xff1a;https://zhuanlan.zhihu.com/p/463418864 1、下载Prometheus&#xff08;普罗米修斯&#xff09; https://prometheus.io/download/ 进入下载文件夹&#xff0c;比如prometheus-2.44.0.windows-amd64。 然后双击Prometheus.exe启动软件。 启动后&#xff0…

AIGC浪潮下,鹅厂新一代前端人的真实工作感受

&#x1f449;腾小云导读 AIGC 这一时代潮流已然不可阻挡&#xff0c;我们要做的不是慌乱&#xff0c;而是把握住这个时代的机会。本文就和大家一起来探索在 AIGC 下&#xff0c;前端工程师即将面临的挑战和机遇。聊聊从以前到现在&#xff0c;AIGC 给我们带来了怎么样的变化&a…

4.9 x64dbg 内存处理与差异对比

LyScript 插件中针对内存读写函数的封装功能并不多&#xff0c;只提供了最基本的内存读取和内存写入系列函数的封装&#xff0c;本章将继续对API接口进行封装&#xff0c;实现一些在软件逆向分析中非常实用的功能&#xff0c;例如ShellCode代码写出与置入&#xff0c;内存交换&…

2 Alice的果园

2 Alice的果园 作者: 赵晓鹏时间限制: 1S章节: 动态规划与贪心 输入说明 : 见题目描述。 输出说明 : 见题目描述。 输入范例 : 1 28 输出范例 : 28 Online Judge 1.0 #include<iostream> #include<vector> using namespace std; int rob(vector<int&…

数学建模学习之简单设备分配问题

简单的设备分配问题 某公司新购置了某种设备 6台&#xff0c;欲分配给下属的4 个企业&#xff0c;已知各企业获得这种设备后年创利润如表 1.1 所示&#xff0c;单位为千万元。问应如何分配这些设备能使年创总利润最大&#xff0c;最大利润是多少? 表1.1的数据为&#xff1a; 对…

Unreal 5 游戏框架

之前&#xff0c;只是简单的实现了一些特定的功能&#xff0c;这几天一直在学习官方的案例&#xff0c;学习了Lyra初学者项目和Action RPG的项目&#xff0c;也从中学习到了很多功能的使用&#xff0c;并对基础的架构设计有了初步的认识。 接下来&#xff0c;将对基础的一些设置…

elementui自定义loading图标

效果图如下&#xff1a; 一、在assets下新建一个mycss.css文件夹&#xff08;图片大小以及文字样式&#xff0c;可以根据自己的需求进行微调&#xff09; .el-loading-spinner {/*这个是自己想设置的 gif 加载动图*/background-image: url(../gif2.gif); background-repeat: n…