您当前的位置:首页 > 电脑百科 > 软件技术 > 应用软件

在浏览器中异步下载文件监听下载进度

时间:2020-09-15 13:53:44  来源:  作者:

在浏览器中异步下载文件,其实就是把服务器响应的文件先保存在内存中。然后再一次下载到磁盘。第二次下载过程,就是把内存的数据IO到磁盘,没有网络开销。速度极快。

之所以要先保存在内存,主要是可以在下载开始之前和下载结束后可以做一些业务逻辑(例如:校验,判断),还可以监听下载的进度。

演示

这里演示一个Demo,在点击下载摁钮后,弹出加loading框。在读取到服务器的响应的文件后。关闭loading框。并且在控制台中输出下载的进度。

有点像是监听文件下载完毕的意思,也只能是像。从内存IO到磁盘的这个过程,JS代码,再也无法染指过程。更谈不上监听了。

Controller

服务端的下载实现

import JAVA.io.BufferedInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMApping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequestMapping("/download")
public class DownloadController {
		@GetMapping
	public void download (HttpServletRequest request,
							HttpServletResponse response,							@RequestParam("file") String file) throws IOException {
				Path path = Paths.get(file);
		if (Files.notExists(path) || Files.isDirectory(path)) {
			// 文件不存在,或者它是一个目录
			response.setStatus(HttpServletResponse.SC_NOT_FOUND);
			return ;
		}
		
		String contentType = request.getServletContext().getMimeType(file);
		if (contentType == null) { 
			// 如果没读取到ContentType,则设置为默认的二进制文件类型
			contentType = "application/octet-stream";
		}
		
		
		try (BufferedInputStream bufferedInputStream = new BufferedInputStream(Files.newInputStream(path))){
			response.setContentType(contentType);
			response.setHeader("Content-Disposition", "attachment; filename=" + new String(path.getFileName().toString().getBytes("GBK"), "ISO-8859-1"));
			
			// 关键点,给客户端响应Content-Length头,客户端需要用此来计算下载进度
			response.setContentLengthLong(Files.size(path));
			
			OutputStream outputStream = response.getOutputStream();
			
			byte[] buffer = new byte[8192];
			
			int len = 0;
			
			while ((len = bufferedInputStream.read(buffer)) != -1) {
				outputStream.write(buffer, 0, len);
			}
			
		} catch (IOException e) {
			
		}
	}
}

Index.html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>异步下载</title>
	</head>
	<body>
		<input name="name" value="D:\eclipse-jee-2019-12-R-win32-x86_64.zip" placeholder="输入你要下载的文件路径" id="file" />
		<button id="button" onclick="downlod();">开始下载</button>
	</body>
	<script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
	<script src="/layer/layer.js"></script>
	<script type="text/JavaScript">
		function downlod(){
			const file = document.querySelector('#file').value;
			if (!file){
				alert('请输入合法的文件地址');
			}
			
			// 打开加载动画
			const index = layer.load(1, {
  				shade: [0.1,'#fff']
			});
			
			const xhr = new XMLHttpRequest();
			xhr.open('GET', '/download?file=' + encodeURIComponent(file));
			xhr.send(null);
			// 设置服务端的响应类型
			xhr.responseType = "blob";
			// 监听下载
			xhr.addEventListener('progress', event => {
				// 计算出百分比
				const percent  = ((event.loaded / event.total) * 100).toFixed(2);
				console.log(`下载进度:${percent}`);
			}, false);
			xhr.onreadystatechange = event => {
				if(xhr.readyState == 4){
					if (xhr.status == 200){
						
						// 获取ContentType
						const contentType = xhr.getResponseHeader('Content-Type');
						
						// 文件名称
						const fileName = xhr.getResponseHeader('Content-Disposition').split(';')[1].split('=')[1];
						
						// 创建一个a标签用于下载
						const donwLoadLink = document.createElement('a');
						donwLoadLink.download = fileName;
						donwLoadLink.href = URL.createObjectURL(xhr.response);
						
						// 触发下载事件,IO到磁盘
						donwLoadLink.click();
						
						// 释放内存中的资源
						URL.revokeObjectURL(donwLoadLink.href);
						
						// 关闭加载动画
						layer.close(index);
					} else if (response.status == 404){
						alert(`文件:${file} 不存在`);
					} else if (response.status == 500){
						alert('系统异常');
					}
				}
			}
		}
	</script>
</html>

现在的ajax请求,几乎都是用ES6的fetch,支持异步,而且代码也更优雅。API设计得更合理。但是目前为止,好像fetch并没有progress事件,也就说它不支持监听上传下载的进度。所以没辙,还是得用XMLHttpRequest。

最后

这种方式弊端也是显而易见,如果文件过大。那么内存就炸了。我觉得浏览器应该暴露一个js的接口。允许通过异步的方式直接下载文件IO到磁盘,通过回调给出下载的进度,IO的进度。

原文:https://springboot.io/t/topic/2734



Tags:浏览器   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
一. 配置yum源在目录 /etc/yum.repos.d/ 下新建文件 google-chrome.repovim /etc/yum.repos.d/google-chrome.repo按i进入编辑模式写入如下内容:[google-chrome]name=googl...【详细内容】
2021-12-23  Tags: 浏览器  点击:(7)  评论:(0)  加入收藏
Safari是苹果在iPhone和iPad上的默认网络浏览器。虽然我们天天都在使用,但是,你是否深入研究了Safari的所有功能和设置?"无痕浏览"、"阅读器"视图和下载文件等标准选项只是其...【详细内容】
2021-12-16  Tags: 浏览器  点击:(20)  评论:(0)  加入收藏
大家好,我是Stark-C。油猴简介【油猴】一款免费的浏览器扩展和最为流行的用户脚本管理器,它是一个附加组件(扩展程序),让用户安装一些脚本使大部分HTML为主的网页改变得更方便易...【详细内容】
2021-12-13  Tags: 浏览器  点击:(43)  评论:(0)  加入收藏
年末,又到了各大厂商盘点年度最佳的时候了。不过让世超感到意外的是 Google 竟然给自己 Chrome 的插件,做了一个 2021 年精选集锦,挑选出了 13 款今年最热门的 Chrome 插件。...【详细内容】
2021-12-13  Tags: 浏览器  点击:(19)  评论:(0)  加入收藏
当我们浏览知乎、Youtube、贴吧、CSDN等等,总会遇到服务商一些广告;复制文章的时候,剪切板总是自带一些版权信息;还有一些网页配色很亮,眼睛看着很不舒服。反正就是各种不爽。给...【详细内容】
2021-12-08  Tags: 浏览器  点击:(27)  评论:(0)  加入收藏
谷歌访问助手插件是专门针对chrome谷歌浏览器而开发的一款访问插件,可以为谷歌搜索,谷歌chrome商店,gmail邮箱提供加速服务,解决打不开的问题。这款插件可以帮助我们在使用谷歌...【详细内容】
2021-12-03  Tags: 浏览器  点击:(12)  评论:(0)  加入收藏
微软似乎正努力增强 Edge 浏览器和网页端 Office 之间的整合联动。Reddit 社区用户 u/Leopeva64-2指出,Edge Canary 的最新版本在标签的右键菜单中有一个新选项。如果你在窗...【详细内容】
2021-11-11  Tags: 浏览器  点击:(35)  评论:(0)  加入收藏
IOS15推送后,Safari也支持扩展了,这里给大家推荐几款Safari扩展软件,希望对你手机使用有所帮助。 扩展功能 IOS15可以通过设置&mdash;&mdash;Safari浏览器&mdash;&mdash;更多扩...【详细内容】
2021-11-08  Tags: 浏览器  点击:(131)  评论:(0)  加入收藏
一、判断是否IE浏览器(支持判断IE11与edge)function IEVersion() {var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串var isIE = userAgent.indexOf("comp...【详细内容】
2021-11-02  Tags: 浏览器  点击:(39)  评论:(0)  加入收藏
作为当今最差的浏览器,虽说IE即将推出历史的舞台,但是因为项目需要还是需要支持。那么必须判断是否是IE,如果是IE,需要做些特殊处理。document.documentMode 是IE特有的属性,可以...【详细内容】
2021-10-25  Tags: 浏览器  点击:(35)  评论:(0)  加入收藏
▌简易百科推荐
ACDSee Pro 2.5 和ACDSee 2009(也就是 ACDSee 11)这两个版本,虽然图标最丑,但却是最适合目前使用的版本。(以前的ACDSee 3.1是第三方改装版,现在出现不稳定了,经常提示插件错误,虽...【详细内容】
2021-12-27  周星骋Cheng    Tags:ACDSee   点击:(2)  评论:(0)  加入收藏
IT之家 12 月 23 日消息,百度地图今日宣布,第二代车道级导航正式上线。据介绍,百度地图第二代车道借助北斗 + 5G,在实现全程车道级导航效果的基础上,全面升级最优车道推荐、全 /...【详细内容】
2021-12-24  IT之家    Tags:百度地图   点击:(10)  评论:(0)  加入收藏
推荐12款不用安装就能免费用的神仙软件,每一款都是百里挑一! 一、文件存储与传输1.不限量网盘地址:https://transferkit.io/一个在线云存储网盘,它提供了不限量的云存储空间,单文...【详细内容】
2021-12-17  牛片网    Tags:软件   点击:(15)  评论:(0)  加入收藏
古人说:凡事预则立不预则废,对于我们当代人来说,做好工作计划,更是职场人高效工作的第一步,所以计划对于我们的重要性不言而喻&hellip;&hellip; 工作表格模板汇总正是因为有了工...【详细内容】
2021-12-15  吴六柒    Tags:工作表格   点击:(32)  评论:(0)  加入收藏
当我们浏览知乎、Youtube、贴吧、CSDN等等,总会遇到服务商一些广告;复制文章的时候,剪切板总是自带一些版权信息;还有一些网页配色很亮,眼睛看着很不舒服。反正就是各种不爽。给...【详细内容】
2021-12-08  小皮虾Pro    Tags:浏览器   点击:(27)  评论:(0)  加入收藏
来源:AirPython作者:星安果 1. 前言大家好,我是安果!之前推荐过很多优秀的 Web 自动化工具,比如:Selenium、Helium、Cypress、Pyppeteer 等利用它们实现自动化的前提是必须安装依...【详细内容】
2021-11-30  CDA数据分析师    Tags:Automa   点击:(30)  评论:(0)  加入收藏
概述superset是由Airbnb开源的轻量级BI分析工具。主要有三大功能:使用数据可视化来探索你的数据,通过交互式的Dashboard来查看你的数据,通过Sql Lab来编写sql查询你的数据。特...【详细内容】
2021-11-30  新视像    Tags:Superset   点击:(21)  评论:(0)  加入收藏
媒体爆料称:近期,老牌音乐播放器Winamp宣布回归,官方网站也大改后重新上线。官方表示:不只是简单更新而是全面重制。新的Winamp 将推出适用于 Windows、macOS 和移动平台的多合...【详细内容】
2021-11-26    中关村在线  Tags:Winamp   点击:(23)  评论:(0)  加入收藏
新版高德地图上线 ADAS 预警导航功能,借助视觉 AI 技术,可智能识别前方车辆、行人,并提供碰撞预警、车道偏离等多种安全提醒,防止风险的发生。 在小联的调研中,只有6%的车机体验...【详细内容】
2021-11-23  手机互联    Tags:高德地图   点击:(143)  评论:(0)  加入收藏
朋友委托我帮忙看看可用邮箱大全有哪些?好用的企业邮箱是多少?他公司要开通企业邮箱。相信很多公司在考虑开通企业邮箱时,都会遇到这样的问题,企业邮箱哪个好?怎样选择合适的企业...【详细内容】
2021-11-11  超级打工人    Tags:企业邮箱   点击:(30)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条