js实现跨域下载,展示下载进度以及自定义下载名称功能

news2025/4/18 15:21:25

在这里插入图片描述

一、 下载进度

  1. loading弹窗结构
// loading状态DOM
function setLoading() {
    let content = document.querySelector('.loading')
    content.innerHTML = ''
    content.innerHTML = `
    <div class="loading_content">
        <div class="contentBox">
            <div class="downloadTip">
                <div class="tips">下载成功!</div>
                <div class="close">
                    <img src="../img/img1/close.png" alt="">
                </div>
            </div>


            <div class="box">
                <div class="tip">预计下载时长10-15s, 请耐心等待</div>
                <div class="progress-container">
                    <div class="progress-bar"></div>
                    <div class="progress-text"></div>
                    <div class="particles">
                        <div class="particle"></div>
                        <div class="particle"></div>
                        <div class="particle"></div>
                        <div class="particle"></div>
                        <div class="particle"></div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    `
}
  1. loading弹窗样式

.loading_content{
    /* display: none; */
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.7);
    z-index: 5;
    font-size: 15px;
}


.loading_content .contentBox {
    display: block;
    position: relative;
    left: 50%;
    top: 50%;
    transform: translateX(-50%) translateY(-50%);
    width: 337px;
    height: 168px;
    padding: 20px;
    background:  url("../img/dialog.png") no-repeat center;
    background-size: contain;
}

.loading_content .contentBox .box ,
.loading_content .contentBox .downloadTip{
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
}
.loading_content .contentBox .downloadTip {
    position: relative;
    display: none;
    color: #fff;
}
.loading_content .contentBox .downloadTip .close {
    position: absolute;
    cursor: pointer;
    top: 0;
    right: 0;
    width: 25px!important;
    height: 25px!important;
}
.loading_content .contentBox .downloadTip .close img {
    width: 100%;
    height: 100%;
}
.loading_content .contentBox .downloadTip .tips {
    position: relative;
    top: 50%;
    left: 50%;
    width: 100%;
    height: 50%;
    line-height: 84px;
    text-align: center;
    transform: translateX(-50%) translateY(-50%);
    font-size: 22px;
}

.loading_content .contentBox .box .tip {
    width: 100%;
    text-align: center;
    line-height: 75px;
    color: #C9B387;
}


.progress-container {
    position: relative;
    width: 100%;
    max-width: 500px;
    height: 20px;
    background: radial-gradient(circle, #1b2735, #090a0f);
    border-radius: 30px;
    overflow: hidden;
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.5);
    box-sizing: border-box;
    border: 1px solid #313131;
  }
  
  .progress-bar {
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    background: linear-gradient(90deg, #c9b386, rgb(146, 24, 22));
    border-radius: 30px;
    animation: grow 7s ease-in forwards;
    box-shadow:
      0 0 15px #c9b386,
      0 0 30px rgb(146, 24, 22);
  }
  
  .progress-bar::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 200%;
    height: 200%;
    background: radial-gradient(circle, rgba(255, 255, 255, 0.15), transparent);
    opacity: 0.5;
    animation: ripple 15s infinite;
  }
  
  .progress-text {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-size: 10px;
    font-weight: bold;
    letter-spacing: 1px;
    color: #fff;
    text-shadow: 0 2px 4px rgba(0, 0, 0, 0.7);
    z-index: 2;
  }
  
  .particles {
    position: absolute;
    width: 100%;
    height: 100%;
    overflow: hidden;
  }
  
  .particle {
    position: absolute;
    width: 4px;
    height: 4px;
    background: #fff;
    border-radius: 50%;
    opacity: 0.6;
    animation: float 5s infinite ease-in-out;
  }
  
  @keyframes grow {
    0% {
      width: 0;
    }
    100% {
      width: 99%;
    }
  }
  
  @keyframes ripple {
    0% {
      transform: translate(-50%, -50%) scale(0.5);
      opacity: 0.7;
    }
    100% {
      transform: translate(-50%, -50%) scale(1.5);
      opacity: 0;
    }
  }
  
  @keyframes float {
    0% {
      transform: translateY(0) translateX(0);
    }
    50% {
      transform: translateY(-20px) translateX(10px);
    }
    100% {
      transform: translateY(0) translateX(0);
    }
  }
  .particle:nth-child(1) {
    top: 10%;
    left: 20%;
    animation-delay: 0s;
  }
  .particle:nth-child(2) {
    top: 30%;
    left: 70%;
    animation-delay: 1s;
  }
  .particle:nth-child(3) {
    top: 50%;
    left: 50%;
    animation-delay: 2s;
  }
  .particle:nth-child(4) {
    top: 80%;
    left: 40%;
    animation-delay: 1.5s;
  }
  .particle:nth-child(5) {
    top: 90%;
    left: 60%;
    animation-delay: 2.5s;
  }
  
  1. 开始显示loading
// 开始动画
function loadingStart() {
    let text = document.querySelector('.progress-text')
    text.innerText = '0%'
    let flag = 0
    timer = setInterval(() => {
        if (text.innerText == '99%') {
            clearInterval(timer)
            return
        }
        flag += 7
        if (flag == 98) {
            flag = 99
        }
        let data = flag
        text.innerText = `${data}%`
    }, 500)
}
  1. 结束loading状态
}
// 结束动画
function loadingDone() {
    timer && clearInterval(timer)
    // 下载完成
    $('.progress-text').html('100%')
    $('.progress-bar').css('animation', 'unset')
    $('.progress-bar').css('width', '100%')
    setTimeout(() => {
        // 结果页面显示,loading页面隐藏
        $('.box').css('display', 'none')
        $('.downloadTip').css('display', 'block')
        $('.close').click(function () {
            $('.loading').html('')
        });
    }, 1500)
}

二、 跨域下载与 自定义名称

主要通过请求获取blob来进行下载

  1. 获取blob
// 异步下载任务
function getBlob(url) {
   return new Promise(resolve => {
       try {
           const xhr = new XMLHttpRequest();
           xhr.open('GET', url, true);
           xhr.responseType = 'blob';
           xhr.onload = () => {
               if (xhr.status === 200) {
                   resolve(xhr.response);
               } else {
                   window.location.href = url;
                   $('.loading').html('')
               }
           };
           xhr.send();
       } catch (error) {
           window.location.href = url;
           $('.loading').html('')
       }

   });
}
  1. 下载与命名

function downloadHandler(blob, url, code) {
    let name = url.split('/').pop()
    var link = document.createElement('a');
    link.href = window.URL.createObjectURL(blob);
    if (code) {
        // .exe替换成code+.exe
        link.download = name.replace(/\.exe$/, '_' + code + '.exe')
    } else {
        link.download = name
    }
    link.click();
}

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

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

相关文章

MCP 实战系列(Day 2)- 动手搓个文件系统 MCP 服务器

上期回顾&#xff1a;MCP 实战系列&#xff08;Day 1&#xff09;- 什么是 MCP&#xff1f; 在上期文章中&#xff0c;我们详细介绍了 Model Context Protocol&#xff08;MCP&#xff09;的基本概念和应用场景。本节将带领大家开发一个简易的 Filesystem MCP Server&#xff…

LabVIEW运动控制(三):EtherCAT运动控制器的高效加工指令自定义封装

ZMC408CE 高性能总线型运动控制器 ZMC408CE是正运动推出的一款多轴高性能EtherCAT总线运动控制器&#xff0c;具有EtherCAT、EtherNET、RS232、CAN和U盘等通讯接口&#xff0c;ZMC系列运动控制器可应用于各种需要脱机或联机运行的场合。 ZMC408CE支持PLC、Basic、HMI组态三种编…

Xilinx虚拟输入/输出(VIO)IP核详细介绍及使用示例

LogiCORE™ IP虚拟输入/输出(VIO)内核是一款可定制化的内核,能够实时监控和驱动FPGA(现场可编程门阵列)内部信号。其输入和输出端口的数量及位宽均可根据需求定制,以便与FPGA设计进行接口对接。由于VIO内核与被监控和/或驱动的设计保持同步,因此应用于您设计中的所有设计…

Vue3+Vite+TypeScript+Element Plus开发-09.登录成功跳转主页

系列文档目录 Vue3ViteTypeScript安装 Element Plus安装与配置 主页设计与router配置 静态菜单设计 Pinia引入 Header响应式菜单缩展 Mockjs引用与Axios封装 登录设计 登录成功跳转主页 多用户动态加载菜单 Pinia持久化 动态路由-配置 文章目录 目录 系列文档目…

Linux : 内核中的信号捕捉

目录 一 前言 二 信号捕捉的方法 1.sigaction()​编辑 2. sigaction() 使用 三 可重入函数 四 volatile 关键字 一 前言 如果信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,这称为捕捉信号。在Linux: 进程信号初识-CSDN博客 这一篇中已经学习到了一种信号…

开发效率提升200%——cursor

cursor带来的编程"革命" 高级语言编程转为"自然语言编程"借助cursor&#xff0c;直接超越初级后台开发、超越初级前端开发、超越初级测试、超越初级UI&#xff0c;产研一体linux命令只用学不用记&#xff0c;语言描述就是命令给一个表结构流程提示词&…

微软庆祝它成立整整50周年

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

SpringBoot 整合 MCP

SpringBoot 整合 MCP MCP MCP 协议主要分为&#xff1a; Client 客户端&#xff08;一般就是指 openai&#xff0c;deepseek 这些大模型&#xff09;Server 服务端&#xff08;也就是我们的业务系统&#xff09;我们要做的就是把我们存量系统配置成 MCP Server 环境 JDK17…

【详细】MySQL 8 安装解压即用 (包含MySQL 5 卸载)

卸载MySQL 1.卸载 2.安装目录删除残余文件&#xff08;当初安装的位置&#xff09; 3.删除programData下面的mysql数据文件 4.检查mysql服务是否存在&#xff0c;如果存在则删除&#xff08;先暂停mysql服务&#xff09; sc delete mysql 5.删除注册表中残留信息 安装MySQL 8&…

显示器各类异常处理方法

显示器各类异常处理方法 导航 文章目录 显示器各类异常处理方法导航画面无显示/黑屏/无HDMI信号输入显示器闪烁显示器花屏显示画面模糊或扭曲显示器颜色异常显示器出现死点或亮点 画面无显示/黑屏/无HDMI信号输入 ​ 首先应该检查的是显示器电源&#xff08;真的有人弄掉电源…

一、简单的 Django 服务

一、配置虚拟环境 1.1 创建一个文件夹在导航栏输入cmd打开 1.2 安装依赖两个库 pip install virtualenv virtualenvwrapper-win -i https://pypi.tuna.tsinghua.edu.cn/simple验证是否安装成功 virtualenv --version pip show virtualenvwrapper-win 1.3 创建虚拟环境 mkvi…

k8s黑科技:Linux+Vagrant+VirtualBox开启Kubernetes奇幻之旅

文章目录 1. 准备硬件2. 安装系统3. 安装 VNC4. 基础配置4.1 路由转发4.2 防火墙4.3 selinux4.4 安装包4.5 重启 5. 配置代理6. 安装 virtuabox7. 安装 vagrant8. 配置 kubespray8.1 安装依赖工具8.2 定制 Vagrantfile8.3 配置代理与时间同步8.4 配置私有镜像仓库 9. 安装虚拟机…

34% 关税冲击下 LabVIEW 开发的变局

2025 年 4 月 4 日&#xff0c;中国国务院关税税则委员会宣布&#xff0c;自 4 月 10 日起对原产于美国的所有进口商品加征 34% 关税。这一举措&#xff0c;给 LabVIEW 开发领域带来显著影响&#xff0c;相关使用者和用户亟需采取应对策略。 ​ 从成本层面看&#xff0c;LabVI…

Http代理服务器选型与搭建

代理服务器选型-Squid 缓存加速 缓存频繁访问的网页、图片等静态资源&#xff0c;减少对原始服务器的重复请求&#xff0c;提升响应速度支持HTTP、HTTPS、FTP等协议&#xff0c;通过本地缓存直接响应客户端请求 访问控制 基于ACL&#xff08;访问控制列表&#xff09;实现精细…

Linux主要开发工具之gcc、gdb与make

此系列还有两篇&#xff0c;大家想完整掌握可以阅读另外两篇 Linux文本编辑与shell程序设计-CSDN博客 Linux基础知识详解与命令大全&#xff08;超详细&#xff09;-CSDN博客 1.gcc编译系统 1.1 文件名后缀 文件名后缀 文 件 类 型 文件名后缀 文 件 类 型 .c C源…

C++初阶-C++入门基础

目录 ​编辑 1.C的简介 1.1C的产生和发展 1.2C的参考文档 1.3C优势和难度 1.4C学习的建议 2.C的第一个程序 2.1打印Hello world 2.2头文件 2.3namespace命名空间 2.4&#xff1a;&#xff1a;作用域限定符 2.5namespace的延伸 2.6C的输入输出 3.总结 1.C的简介 …

idea手动创建resources文件夹

有时maven没有构建成功可能造成&#xff0c;resources文件夹不创建的现象 此时我们可以手动创建 手动创建

第十五届蓝桥杯大赛软件赛省赛Python 大学 C 组题目试做(中)【本期题目:回文数组,挖矿】

OK&#xff0c;继续写我们的第十五届蓝桥杯大赛软件赛省赛Python 大学 C 组题目&#xff0c;后面的题目比较麻烦了&#xff0c;所以我们再分两期讲。 这一期的题有 &#xff1a; 回文数组&#xff0c;挖矿 文章目录 回文数组基本思路第一步&#xff0c;获取半个数组每个数需要…

Qt动画 QAbstractAnimation

文章目录 简介QVariantAnimation 数值动画QPropertyAnimation 属性动画 QAnimationGroup 一组动画QParallelAnimationGroup 并行动画组QSequentialAnimationGroup 串行动画组 简介 QAbstractAnimation 是所有 Qt 动画的基类。 该类定义了所有动画应该都会有的功能函数。 要想实…

SpringMvc的请求-获得请求参数

客户端请求参数的格式是: namevalue&namevalue..… 服务器端要获得请求的参数&#xff0c;有时还需要进行数据的封装&#xff0c;SpringMVC可以接收如下类型的参数: 基本类型参数 POJO类型参数 数组类型参数 集合类型参数 获得基本类型参数 Controller中的业务方法…