http网络请求与下载进度

2024-09-08 03:04
文章标签 http 请求 网络 下载 进度

本文主要是介绍http网络请求与下载进度,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Http_request 目录

一、XMLHttpRequest

在使用 Fetch API 进行网络请求时,原生的 Fetch API 并不直接支持获取下载进度的功能,因为 Fetch API 主要是基于 Promise 的,它主要关注于请求的成功或失败,以及响应数据的处理,而不直接处理像进度跟踪这样的底层细节。

不过,你可以通过一些技巧或方法间接实现下载进度的跟踪。以下是一些常用的方法:

1. 使用 XMLHttpRequest

虽然 Fetch API 较为现代,但如果你需要跟踪下载进度,XMLHttpRequest 可能是一个更好的选择。XMLHttpRequest 提供了 onprogress 事件,可以用来追踪下载进度。

var xhr = new XMLHttpRequest();
xhr.open('GET', 'your-file-url', true);
xhr.responseType = 'blob';xhr.onprogress = function (e) {if (e.lengthComputable) {var percentComplete = (e.loaded / e.total) * 100;console.log(percentComplete + '% downloaded');}
};xhr.onload = function () {if (this.status == 200) {// 处理响应数据}
};xhr.send();

在上述代码中,我们创建了一个 XMLHttpRequest 对象,并设置了 onprogress 事件处理函数。在该函数中,通过判断 e.lengthComputable 是否为真,来确定是否可以计算下载进度。如果可以计算,则通过 e.loaded 和 e.total 计算出已下载的百分比,并将其打印到控制台

2.XMLHttpRequest 的进一步封装

   xhrToDownload(options, onProgress, onSuccess, onError) {return new Promise((resolve, reject) => {const xhr = new XMLHttpRequest();xhr.open(options.method || 'GET', options.url);xhr.responseType = options.responseType || 'blob';xhr.onprogress = function(e) {if (e.lengthComputable) {const progress = (e.loaded / e.total) * 100;onProgress && onProgress(progress);}};xhr.onload = function(e) {if (xhr.status === 200) {// onSuccess && onSuccess(xhr.response);console.log('上传成功', xhr);resolve({ status: xhr.status, data: xhr.response })} else {onError && onError(xhr.statusText);reject({ status: xhr.status, data: xhr.statusText }); // 拒绝 Promise}}xhr.onerror = function(e) {onError && onError(xhr.statusText);reject({ status: xhr.status, data: xhr.statusText }); // 拒绝 Promise};xhr.send();});},

这个示例进一步封装了 XMLHttpRequest,使其可以返回一个 Promise,方便进行异步处理。

3. 创建 a 标签下载

        downloadFile(blob, fileName = '2.mp4') {// 创建a 标签const a = document.createElement('a');const blobUrl = URL.createObjectURL(blob);a.setAttribute('href', blobUrl);a.setAttribute('download', fileName);a.style.display = 'none';document.body.appendChild(a);a.click();document.body.removeChild(a);URL.revokeObjectURL(blobUrl)},

使用实例:

    async downloadVideo(row) {const url = row.path;if (!url) {return;}var index = this.tableData.findIndex(item => item.id === row.id);// 使用示例const response = await this.xhrToDownload({ url: url }, (progress) => {console.log('Download progress:', progress);if (index !== -1) {this.tableData[index].downLoadProgress = progress}}, (res) => {// 这里处理 Blob,例如保存到 IndexedDB、FileSystem API 或其他console.log('Download successful:', res);// 如果你确实需要下载文件,可以在这里创建 <a> 标签并触发点击}, (error) => {console.error('Download failed:', error);})if (response && response.status === 200) {this.downloadFile(response.data)}},

二、 Fetch API

1. 使用 Fetch API

  • 链式调用

            fetch(url).then(res => {return res.blob()}).then(res => {console.log('res', res);})
    
  • async - await 语法糖

        // const response = await fetch(url)// const blod = await response.blob()

2. 使用 Stream API 和 ReadableStream

Fetch API 支持响应体作为 ReadableStream,但直接使用它来跟踪进度可能不太直观。不过,你可以通过监听流的读取操作来大致估计进度(虽然这通常不如 XMLHttpRequest 那样精确)。

    //your_file_url fetch('http://127.0.0.1:456/proxy/DJI_0003.MP4')fetch('http://127.0.0.1:456/proxy/DJI_0003.MP4').then(response=>{console.log(response);const reader = response.body.getReader() //  ReadableStreamconst contentLength = response.headers.get('content-length')let readTotal = 0if(!contentLength){console.log('无法获取进度');return}const sizeTotal = parseInt(contentLength)const chunks =[]function read(){reader.read().then(({done,value})=>{if(done){console.log('下载完成');const type = response.headers.get('content-type')const blob = new Blob(chunks,{type})return}readTotal += value.lengthconst progress = Math.ceil(readTotal/sizeTotal*100)console.log('下载进度:',progress);chunks.push(value)read()})}read()})

注意:上面的代码示例并不直接计算下载进度,因为 ReadableStream API 并不直接提供总大小信息(除非你在响应头中通过 Content-Length 获取)。你需要有一个方式来获取文件的总大小,以便能够计算进度。

3. 使用fetch下载并获取进度

简单获取下载进度fetchToDownlod(url, options, onProgress, onSuccess, onError) {try {// eslint-disable-next-line no-async-promise-executorreturn new Promise(async(resolve, reject) => {const response = await fetch(url, options);const reader = response.body.getReader();// Step 2:获得总长度(length)const contentLength = +response.headers.get('Content-Length');console.log('contentLength', contentLength);// Step 3:读取数据let receivedLength = 0; // 当前接收到了这么多字节const chunks = []; // 接收到的二进制块的数组(包括 body)// eslint-disable-next-line no-constant-conditionwhile (true) {const { done, value } = await reader.read();if (done) {// 如果没有更多的数据可读,则退出循环break;}chunks.push(value);receivedLength += value.length;const progress = Math.round(receivedLength / contentLength * 100);onProgress && onProgress(progress);}// 将响应体转换为 Blob 对象const blob = new Blob(chunks, { type: 'application/octet-stream' });if (response.status === 200) {resolve({ status: response.status, blob });}if (response.status === 404) {reject({ status: response.status, blob });}});} catch (err) {console.log('err', err);return Promise.reject(err);}},

调用实例:

       async downloadVideo(row) {const url = row.path;if (!url) {return;}let fileName = 'text.mp4'const lastIndex = url.lastIndexOf('/');if (lastIndex !== -1) {fileName = url.substring(lastIndex + 1);}var index = this.tableData.findIndex(item => item.id === row.id);const options = {method: 'GET', // *GET, POST, PUT, DELETE, etc.mode: 'cors', // no-cors, *cors, same-origincache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cachedcredentials: 'same-origin', // include, *same-origin, omitresponseType: 'blob', //重要代码'Access-Control-Allow-Origin': '*','Access-Control-Allow-Credentials': true,headers: {'Content-Type': 'application/json'}}const res = await this.fetchToDownlod(url, options, (progress) => {// console.log('Download progress:', progress);if (index !== -1) {this.tableData[index].downLoadProgress = progress}})console.log('res', res);if (!res || res.status !== 200) {return this.$message.error('下载失败')}this.downloadFile(res.blob, fileName)},

结论

如果你的应用需要精确地跟踪下载进度,并且你的环境允许,使用 XMLHttpRequest 可能是最直接和简单的方法。如果你正在寻找更现代的方法,并可以接受一些复杂性,你可以考虑使用 Service Workers 或 Stream API 来实现类似的功能。

这篇关于http网络请求与下载进度的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1146928

相关文章

常用的jdk下载地址

jdk下载地址 安装方式可以看之前的博客: mac安装jdk oracle 版本:https://www.oracle.com/java/technologies/downloads/ Eclipse Temurin版本:https://adoptium.net/zh-CN/temurin/releases/ 阿里版本: github:https://github.com/

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

ASIO网络调试助手之一:简介

多年前,写过几篇《Boost.Asio C++网络编程》的学习文章,一直没机会实践。最近项目中用到了Asio,于是抽空写了个网络调试助手。 开发环境: Win10 Qt5.12.6 + Asio(standalone) + spdlog 支持协议: UDP + TCP Client + TCP Server 独立的Asio(http://www.think-async.com)只包含了头文件,不依

BUUCTF靶场[web][极客大挑战 2019]Http、[HCTF 2018]admin

目录   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 [web][HCTF 2018]admin 考点:弱密码字典爆破 四种方法:   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 访问环境 老规矩,我们先查看源代码

poj 3181 网络流,建图。

题意: 农夫约翰为他的牛准备了F种食物和D种饮料。 每头牛都有各自喜欢的食物和饮料,而每种食物和饮料都只能分配给一头牛。 问最多能有多少头牛可以同时得到喜欢的食物和饮料。 解析: 由于要同时得到喜欢的食物和饮料,所以网络流建图的时候要把牛拆点了。 如下建图: s -> 食物 -> 牛1 -> 牛2 -> 饮料 -> t 所以分配一下点: s  =  0, 牛1= 1~

poj 3068 有流量限制的最小费用网络流

题意: m条有向边连接了n个仓库,每条边都有一定费用。 将两种危险品从0运到n-1,除了起点和终点外,危险品不能放在一起,也不能走相同的路径。 求最小的费用是多少。 解析: 抽象出一个源点s一个汇点t,源点与0相连,费用为0,容量为2。 汇点与n - 1相连,费用为0,容量为2。 每条边之间也相连,费用为每条边的费用,容量为1。 建图完毕之后,求一条流量为2的最小费用流就行了

poj 2112 网络流+二分

题意: k台挤奶机,c头牛,每台挤奶机可以挤m头牛。 现在给出每只牛到挤奶机的距离矩阵,求最小化牛的最大路程。 解析: 最大值最小化,最小值最大化,用二分来做。 先求出两点之间的最短距离。 然后二分匹配牛到挤奶机的最大路程,匹配中的判断是在这个最大路程下,是否牛的数量达到c只。 如何求牛的数量呢,用网络流来做。 从源点到牛引一条容量为1的边,然后挤奶机到汇点引一条容量为m的边

【Linux】应用层http协议

一、HTTP协议 1.1 简要介绍一下HTTP        我们在网络的应用层中可以自己定义协议,但是,已经有大佬定义了一些现成的,非常好用的应用层协议,供我们直接使用,HTTP(超文本传输协议)就是其中之一。        在互联网世界中,HTTP(超文本传输协议)是一个至关重要的协议,他定义了客户端(如浏览器)与服务器之间如何进行通信,以交换或者传输超文本(比如HTML文档)。

2. 下载rknn-toolkit2项目

官网链接: https://github.com/airockchip/rknn-toolkit2 安装好git:[[1. Git的安装]] 下载项目: git clone https://github.com/airockchip/rknn-toolkit2.git 或者直接去github下载压缩文件,解压即可。

如何确定 Go 语言中 HTTP 连接池的最佳参数?

确定 Go 语言中 HTTP 连接池的最佳参数可以通过以下几种方式: 一、分析应用场景和需求 并发请求量: 确定应用程序在特定时间段内可能同时发起的 HTTP 请求数量。如果并发请求量很高,需要设置较大的连接池参数以满足需求。例如,对于一个高并发的 Web 服务,可能同时有数百个请求在处理,此时需要较大的连接池大小。可以通过压力测试工具模拟高并发场景,观察系统在不同并发请求下的性能表现,从而