前言

兄弟们看到这个标题可能会觉得是个标题党,为了解决疑虑,我们先来看下最终的测试结果:

测试云盘下载的文件 46M,自己本地最大下载速度 2M

1. 单线程下载,总耗时: 603s

img

2. 多线程下载,50个线程,总耗时:13s

img

测试结果,提速46倍,我还是太谦虚了,只说提速30倍,此处我们觉得应该有掌声(我听不到,还是点赞实在)

HTTP协议Range请求头

Range主要是针对只需要获取部分资源的范围请求,通过指定Range即可告知服务器资源的指定范围。格式: Range: bytes=start-end

比如:获取字节范围 5001-10000

Range: bytes=5001-10000

1

也可以指定开始位置不指定结束位置,表示获取开始位置之后的全部数据

Range: bytes=5001-

1

服务器接收到带有Range的请求,会在处理请求之后返回状态码为206 Partial Content的响应。

基于Range的特性,我们就可以实现文件的多线程下载,文件的断点续传

准备工作

本文我们使用的SpringMVC中的RestTemplate;由于云盘的链接是Https,所以我们需要设置RestTemplate绕过证书验证

pom.xml

编写

RestTemplate的构造器,以及绕过https的证书验证

在下载的过程中,我们需要知道当前下载的速度是多少,所以需要定义一个显示下载速度的接口

因为计算下载速度,我们需要知道每秒传输的字节数是多少,为了监控传输数据的过程,我们需要了解SpringMVC中的接口ResponseExtractor

该接口只有一个方法,当客户端和服务器端连接建立之后,会调用这个方法,我们可以在这个方法中监控下载的速度。

DisplayDownloadSpeed接口的抽象实现

AbstractDisplayDownloadSpeedResponseExtractor

整个项目主要涉及到的类图

简单的文件下载器

这里使用的是restTemplate调用execute, 先文件获取到字节数组, 再将字节数组直接写到目标文件。

这里我们需要注意的点是: 这种方式会将文件的字节数组全部放入内存中, 及其消耗资源;我们来看看如何实现。

创建

ByteArrayResponseExtractor类继承

AbstractDisplayDownloadSpeedResponseExtractor

调用

restTemplate.execute执行下载,保存字节数据到文件中

测试下载819M的idea

执行一段时间之后,我们可以看到内存已经使用了800M左右,所以这种方式只能使用于小文件的下载,如果我们下载几G的大文件,内存肯定是不够用的。至于下载时间,因为文件太大也没有等下载完成就结束了程序。

单线程大文件下载

上面的方式只能下载小的文件,那大文件的下载我们该用什么方式呢?我们可以把流输出到文件而不是内存中。接下来我们来实现我们大文件的下载。

创建

FileResponseExtractor类继承

AbstractDisplayDownloadSpeedResponseExtractor,把流输出到文件中

文件下载器,先把流输出到临时下载文件(xxxxx.download),下载完成后在重命名文件

测试下载819M的idea

执行一段时间之后,我们再看看下内存的使用情况,发现这种方式内存消耗较少,效果比较理想,下载时间:199s

多线程文件下载

如果服务器不限速的话,通常能够把自己本地的带宽给跑满,那么使用单线程下载就够了,但是如果遇到服务器限速,下载速度远小于自己本地的带宽,那么可以考虑使用多线程下载。多线程我们使用CompletableFuture(可以参考文章 CompletableFuture让你的代码免受阻塞之苦)。

实现多线程文件下载的基本流程:

首先我们通过Http协议的Head方法获取到文件的总大小

然后根据设置的线程数均分文件的大小,计算每个线程的下载的字节数据开始位置和结束位置

开启线程,设置HTTP请求头Range信息,开始下载数据到临时文件

下载完成后把每个线程下载完成的临时文件合并成一个文件

完成代码如下:

开启30个线程测试下载819M的idea

img

从执行的结果上来看,因为开启了30个线程同时在下载,内存的占用要比单线程消耗的多,但是也在接受范围内,下载时间:81s,速度提升2.5倍,这是因为idea的下载服务器没有限速,本次多线程速度的提升仅仅是在充分的压榨本地的带宽,所以提示的幅度不大。

单线程下载和对线程下载对比测试

因为云盘对单个线程的下载速度做了限制,大概是在100kb,所以我们使用云盘的下载链接,来测试多线程和单线程的下载速度。

测试 云盘中 46M 的文件的下载速度,自己本地最大下载速度 2M

获取文件的下载地址

注意:从浏览器中获取的链接需要先使用URLDecode解码,否则下载会失败,并且云盘文件的下载链接是有时效性的,过期后就不能在下载,需要重新生成下载链接

测试单线程下载文件

执行的结果可以看出,云盘对单线程的下载限速真的是丧心病狂, 46M的文件下载需要耗时:600s

测试多线程下载文件

为了充分的压榨网速,找出最合适的线程数,所以测试了不同线程数的下载速度

线程数

下载总耗时

10

60s

20

30s

30

21s

40

15s

50

13s

从测试的结果上来看,对于自己的运行环境把线程数设置在30个左右比较合适

文件断点续传如何实现,欢迎在大家评论区说出自己的思路。

源码地址:https://gitee.com/silently9527/fast-download

有热门推荐

java 下载加速_Java实现大文件下载,提速30倍!想学?我教你啊!相关推荐

  1. Java实现大文件多线程下载,提速30倍!想学?我教你啊

    前言 在上一篇文章 <面试官不讲武德>对Java初级程序猿死命摩擦Http协议 中,我们有提到大文件下载和断点续传,本篇我们就来开发一个多线程文件下载器,最后我们用这个多线程下载器来突破云 ...

  2. java 下载加速_一种基于Java的大文件下载加速方法与流程

    本发明涉及java/多线程技术领域,涉及一种加速文件下载装置,具体提供一种基于java的大文件下载加速方法. 背景技术: 现有的常用下载方式是基于浏览器的单线程下载.这种单线程下载的方式,是通过htt ...

  3. 百度PRNN:增强GPU伸缩性,RNN训练最高提速30倍(源码下载)

    尽管有各种深度学习加速器,神经网络的大小依然受限于计算平台的能力.百度硅谷人工智能实验室高级研究员Greg Diamos在最近的ICML 2016上发表了一篇PRNN(Persistent RNNs) ...

  4. java 下载限速_Java 文件下载限流算法

    在做文件下载功能时,为了避免下载功能将服务器的带宽打满,从而影响服务器的其他服务.我们可以设计一个限流器来限制下载的速率,从而限制下载服务所占用的带宽. 一.算法思路 定义一个数据块chunk(单位 ...

  5. java 流 下载文件_java 流实现文件下载问题

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 用servlet写了一个流下载,文件能正常下载,下载下来也能用,而且后台不报错,但是当我在下载模块的后台初始位置输入System.out.print(&q ...

  6. java 下载工具_java文件下载工具类

    java文件工具类是java开发爱好者提供的一个java开源包,让广大java爱好者以及开发者可以直接编译形成class文件进行使用.内容包含io流,图形界面,使用户更好更快的找到相对应文件,并进行相 ...

  7. java ftp输出流_java输出流实现文件下载

    //导出Excel try { HSSFWorkbook wb = carService.export(list); //调用service方法~! response.setContentType(& ...

  8. java foreach用法_Java十大简单性能优化

    以下是Java中最容易进行的10个性能优化: 1.使用StringBuilder 这几乎是所有Java代码中的默认设置.尽量避免+操作员.当然,您可能会争辩说它StringBuilder无论如何都是语 ...

  9. java 性能 优化_Java十大简单性能优化

    java 性能 优化 关于" web scale "这个流行词有很多炒作,人们花了很多时间来重新组织他们的应用程序体系结构,以使其系统"规模化". 但是什么是扩 ...

最新文章

  1. WCF for .NET CF的一个应用及两个困惑的问题
  2. 网络推广方案中解析SEO优化文章的标题设置技巧
  3. 信息系统项目管理师:第6章:项目进度管理-章节重点汇总
  4. leetcode-125-Valid Palindrome
  5. Activity后台运行一段时间回来crash问题的分析与解决
  6. 二、mongodb数据库系列——聚合操作 索引操作 权限管理
  7. Thrift介绍与应用(三)—hbase的thrift接口
  8. 如异界守塔的伪原创工具
  9. Maven实战(四)——基于Maven的持续集成实践
  10. Kotlin的中文文档
  11. 【一】最新多智能体强化学习方法【总结】
  12. 3d之家开机号计算机网,3d之家最新开机号
  13. Win10易升下载链接
  14. 聊聊量子计算机那些事
  15. IP地址、子网掩码、网络数、主机数、广播地址及其计算方法
  16. linux离线安装及配置redis
  17. 有一个3x4的矩阵,要求编程序求出其中值最大的那个元素的值,以及其所在的行号和列号.
  18. CALIPSO Quality Statements Lidar Level 2 Cloud and Aerosol Layer Products
  19. 【深度学习】OCR文本识别
  20. MPLS 配置远端LDP会话实验 详解

热门文章

  1. 【SE】Week7 : Silver Bullet Cathedral and Bazaar Big Ball of Mud Waterfall ...
  2. HDU 4417 Super Mario(线段树)
  3. threejs实现天空盒
  4. 加密资产涨跌幅度的计算方式
  5. 玩转单细胞高级分析 | 细胞通讯分析篇
  6. 微信小程序中使view占满整个屏幕高度的实现方法
  7. 真正的高手,都在培养系统思维
  8. 解决一个思维惯性问题
  9. 抓住czx【最短路】
  10. figlet:ASCII 艺术字生成器