vue下载大文件时浏览器不显示下载进度

本文探讨Vue项目中下载大文件(如音视频)时如何优化用户体验,介绍使用XMLHttpRequest、a标签配合Nginx配置及AWS SDK等多种方法实现文件下载,并保持良好的交互体验。

vue下载大文件时浏览器不显示下载进度

问题描述

最近开发中遇到个问题,项目需要下载大文件(音视频),由于后端给我的是视频的地址而不是直接返回流,所以前端用了XMLHttpRequest获取视频流并实现下载功能。这时会发现点击下载按钮后会有很长一段时间的空白,页面没任何反正,然后才显示下载完成的文件。这是因为我们需要等获取到流后才触发浏览器下载,获取流会花费很长的时间。

要想实现下载时浏览器能显示下载进度,只能把获取流的请求抛给浏览器,使用a标签的download属性实现下载,代码如下:

let ele = document.createElement('a');
let fileName = 'xxx';
ele.download = fileName;
ele.href = 'url';
ele.style.display = 'none'
document.body.appendChild(ele)
ele.click();
ele.remove();

这时又出现了新的问题,点击后会发现浏览器会自动打开一个新页面播放视频,并没有我们一开始想的那样直接下载;对于这个情况,咨询了下运维,得知可以在nginx里配置解决。

解决方案

nginx配置浏览器下载文件

前端下载总结

1. 使用XMLHttpRequest获取流并下载
let _this = this;
let xhr = new XMLHttpRequest();
xhr.open('GET', this.url, true);
xhr.responseType = 'arraybuffer';    // 返回类型blob
xhr.onload = function () {
  if (xhr.readyState === 4 && xhr.status === 200) {
    let blob = this.response;
    // 转换一个blob链接
    let u = window.URL.createObjectURL(new Blob([blob],{ type: 'video/mp4' }))
    let a = document.createElement('a');
    a.download = fileName;
    a.href = u;
    a.style.display = 'none'
    document.body.appendChild(a)
    a.click();
    a.remove();
  }
};
xhr.send()

缺点

浏览器无法获取下载进度,只在下载完成后会在浏览器左下角出现文件下载完成;若文件比较大的话,从用户点击下载到文件下载完成中间会有一段空白期,用户体验不好。

2. 使用FileSaver下载文件

FileSaver下载文件是基于blob,若后端返回的文件非blob格式,需要先转换后下载;

// 将文件流转换为blob格式
let blob = new Blob([res.data], {
  type: 'application/vnd.ms-excel;charset=utf-8'
})
FileSaver.saveAs(blob格式的文件, "下载的文件命名");
3. 使用a标签+Nginx配置实现下载
let ele = document.createElement('a');
let fileName = 'xxx';
ele.download = fileName;
ele.href = 'url';
ele.style.display = 'none'
document.body.appendChild(ele)
ele.click();
ele.remove();
4. 前端直接从AWS下载文件
// 安装
npm install aws-sdk

// 引入
import AWS from 'aws-sdk'

// AWS下载
AWS.config.update({
  accessKeyId: 'xxxx',
  secretAccessKey: 'xxxx',
  region: 'us-east-2'
})
const s3 = new AWS.S3()
const myBucket = 'xxxx'
const myKey = 'xxxx' // 文件存放的路径
const signedUrlExpireSeconds = 60 * 5

const url = s3.getSignedUrl('getObject', {
  Bucket: myBucket,
  Key: myKey,
  Expires: signedUrlExpireSeconds
})
const link = document.createElement('a')
link.href = url
link.download = 'Q2_MTClient_v1.4.0-19_.txt' // 同域下有效
link.click()
### Vue 实现大文件下载显示浏览器进度条 为了实现在Vue项目中进行大文件下载显示浏览器进度条的功能,可以借鉴NProgress库用于页面跳转进度条逻辑[^2]。过针对文件下载场景,则需进一步调整以适应API请求的特点。 #### 安装依赖 首先,在项目中安装`axios`作为HTTP客户端,因为其能够处理上传/下载操作,并且支持事件监听以便于获取下载进度: ```bash npm install axios ``` 接着按照之前的说明引入`nprogress`来创建视觉上的进度反馈[^4]。 #### 创建服务函数 定义一个专门的服务函数用来发起带有进度监控的大文件下载请求。此部分代码应放置在一个独立的服务模块内或是Vuex store里视具体架构而定。 ```javascript // services/downloadService.js import axios from 'axios'; import NProgress from 'nprogress'; export const downloadLargeFile = async (url, fileName) => { try { NProgress.start(); await axios({ url, method: 'GET', responseType: 'blob', // important onDownloadProgress: progressEvent => { let percentCompleted = Math.floor((progressEvent.loaded * 100) / progressEvent.total); NProgress.set(percentCompleted / 100); } }).then(response => { // Create a Blob object using the response data. var blob = new Blob([response.data], { type: 'application/octet-stream' }); // Create an invisible A element to trigger file save dialog. const link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = fileName; link.click(); // Clean up and complete progress bar after saving file locally. setTimeout(() => { URL.revokeObjectURL(link.href); NProgress.done(); }, 1000); }); } catch (error) { console.error(error); NProgress.done(false); } }; ``` 这段代码通过配置`onDownloadProgress`回调函数实更新进度条状态;当整个过程完成后调用`NProgress.done()`关闭进度指示器。 #### 调用服务函数 最后一步是在适当的地方触发这个下载动作,比如按钮点击事件处理器中: ```html <template> <!-- ... --> <button @click="handleClick">下载</button> <!-- ... --> </template> <script setup> import { ref } from "vue"; import { downloadLargeFile } from "@/services/downloadService"; const handleClick = () => { const url = "/api/large-file"; // Replace with your actual API endpoint const filename = "largefile.zip"; downloadLargeFile(url, filename); } </script> ``` 这样就可以在用户点击按钮后启动带进度提示的大文件下载流程了。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值