HTTP文件断点续传原理解析(源码)

生活中,有许多事物,在没有被揭开面纱之前,我们往往会觉得很神秘很高深,认为它一定很难,进而望而却步,失去了解它的机会。然而,很多事,只要我们自己能沉下心来,细细研究,那些神秘高深的,也会变得简单明了。"HTTP文件断点续传"就是这样一个好例子,深入了解背后之理,“HTTP文件断点续传原理”其实很简单。

一、什么是断点续传

1.定义:

可以从下载或上传断开点继续开始传输,就叫断点续传。

2.核心实现原理:

i.RandomAccessFile(文件任意位置保存)
方法seek():可以移动到保存文件任意位置,在该位置发生下一个读取或写入操作

ii.HttpURLConnection.setRequestProperty()(任意位置请求返回剩余文件)

HttpURLConnection.setRequestProperty(“Range”, “bytes=” + start + “-” + end)

二、实例分析

流程图

实现步骤

  • 1.建立数据库:保存文件下载信息
  • 2.下载服务类(DownloadService)
  • 3.两个线程:文件信息线程(FileInfoThread)和文件下载线程(DownloadThread)
  • 4.广播(BroadcastReceiver):UI进度更新

1.建立数据库
按常规数据库建立方法,具体(略)。数据保存信息为:

/*** 下载信息类*/
public class DownloadInfo {private int id;private String url;//下载链接private long start;//开始大小private long end;//最终大小private long progress;//下载进度
}

2.下载服务类
利用service多次启动只调用onStartCommand()方法,处理开始或暂停下载逻辑。

    public int onStartCommand(Intent intent, int flags, int startId) {if (intent.getAction().equals(ACTION_START)) {FileInfo fileInfo = (FileInfo) intent.getSerializableExtra(TAG_FILEINFO);mFileInfoThread = new FileInfoThread(fileInfo,mHandler);mFileInfoThread.start();} else if (intent.getAction().equals(ACTION_PAUSE)) {if (mDownloadThread != null) {mDownloadThread.setPause(true);}}return super.onStartCommand(intent, flags, startId);}

3.两个线程
i.文件信息线程(FileInfoThread)

通过网络获取下载文件大小,并建立对应大小的保存文件路径。

 HttpURLConnection conn = null;RandomAccessFile raf = null;try {URL url = new URL(mFileInfo.getUrl());conn = (HttpURLConnection) url.openConnection();//连接网络文件conn.setConnectTimeout(3000);conn.setRequestMethod("GET");int length = -1;Log.e(TAG,"HttpResponseCode=="+ conn.getResponseCode() + "");if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {//获取文件长度length = conn.getContentLength();}if (length < 0) {return;}File dir = new File(DownloadService.DOWNLOAD_PATH);if (!dir.exists()) {dir.mkdir();}//在本地创建文件File file = new File(dir, mFileInfo.getFileName());raf = new RandomAccessFile(file, "rwd");//设置本地文件长度raf.setLength(length);mFileInfo.setLength(length);Log.e(TAG,"下载文件大小(size)"+ mFileInfo.getLength() + "");mHandler.obtainMessage(DownloadService.MSG_FILEINFO, mFileInfo).sendToTarget();} catch (Exception e) {e.printStackTrace();} finally {try {if (conn != null && raf != null) {raf.close();conn.disconnect();}} catch (IOException e) {e.printStackTrace();}}

ii.文件下载线程(DownloadThread)
断点续传原理核心类。
1.判断下载进度是否有保存,若无,数据插入一条数据。

        if (!mDatabaseOperation.isExists(downloadInfo.getUrl(), downloadInfo.getId())) {mDatabaseOperation.insert(downloadInfo);}

2.设置网络请求Range参数,从请求位置返回数据

   //设置下载位置long start = downloadInfo.getStart() + downloadInfo.getProgress();connection.setRequestProperty("Range", "bytes=" + start + "-" + downloadInfo.getEnd());

3.通过RandomAccessFile从进度保存位置保存文件

  RandomAccessFile raf;File file = new File(DownloadService.DOWNLOAD_PATH, mFileInfo.getFileName());raf = new RandomAccessFile(file, "rwd");raf.seek(start);...//写入文件raf.write(buffer, 0, len);

4.用户暂停时,保存下载进度

 //下载暂停时,保存进度if (isPause) {Log.e(TAG,"保存进度文件(size):"+progress + "");mDatabaseOperation.update(mFileInfo.getUrl(), mFileInfo.getId(), progress);return;}

4.广播(BroadcastReceiver)
每秒广播一次,刷新UI

 long time = System.currentTimeMillis();......if (System.currentTimeMillis() - time > 1000) {//超过一秒,就刷新UItime = System.currentTimeMillis();sendBroadcast(intent,(int)(progress * 100 / mFileInfo.getLength()));Log.e(TAG,"进度:" + progress * 100 / mFileInfo.getLength() + "%");}

DownloadThread类源码:

/*** 文件下载线程* Created by AwenZeng on 2017/9/6.*/public class DownloadThread extends Thread {private DownloadInfo downloadInfo;private FileInfo mFileInfo;private long progress = 0;private boolean isPause;private DatabaseOperation mDatabaseOperation;private Context mContext;private static final String TAG = "DownloadThread";public DownloadThread(Context context, DatabaseOperation databaseOperation, DownloadInfo threadInfo, FileInfo fileInfo) {this.downloadInfo = threadInfo;mContext = context;mDatabaseOperation = databaseOperation;mFileInfo = fileInfo;}public void setPause(boolean pause) {isPause = pause;}@Overridepublic void run() {if (!mDatabaseOperation.isExists(downloadInfo.getUrl(), downloadInfo.getId())) {mDatabaseOperation.insert(downloadInfo);}HttpURLConnection connection;RandomAccessFile raf;InputStream is;try {URL url = new URL(downloadInfo.getUrl());connection = (HttpURLConnection) url.openConnection();connection.setConnectTimeout(3000);connection.setRequestMethod("GET");//设置下载位置long start = downloadInfo.getStart() + downloadInfo.getProgress();connection.setRequestProperty("Range", "bytes=" + start + "-" + downloadInfo.getEnd());//设置文件写入位置File file = new File(DownloadService.DOWNLOAD_PATH, mFileInfo.getFileName());raf = new RandomAccessFile(file, "rwd");raf.seek(start);progress += downloadInfo.getProgress();Log.e(TAG,"下载文件进度(size):"+ downloadInfo.getProgress() + "");Log.e(TAG,"HttpResponseCode ==="+connection.getResponseCode() + "");//开始下载if (connection.getResponseCode() == HttpURLConnection.HTTP_PARTIAL) {Log.e(TAG,"剩余文件(size):"+connection.getContentLength() + "");Intent intent = new Intent(DownloadService.ACTION_UPDATE);//广播intentis = connection.getInputStream();byte[] buffer = new byte[1024 * 4];int len = -1;long time = System.currentTimeMillis();while ((len = is.read(buffer)) != -1) {//下载暂停时,保存进度if (isPause) {Log.e(TAG,"保存进度文件(size):"+progress + "");mDatabaseOperation.update(mFileInfo.getUrl(), mFileInfo.getId(), progress);return;}//写入文件raf.write(buffer, 0, len);//把下载进度发送广播给Activityprogress += len;if (System.currentTimeMillis() - time > 1000) {//超过一秒,就刷新UItime = System.currentTimeMillis();sendBroadcast(intent,(int)(progress * 100 / mFileInfo.getLength()));Log.e(TAG,"进度:" + progress * 100 / mFileInfo.getLength() + "%");}}sendBroadcast(intent,100);/***  删除下载信息(重新下载)*/mDatabaseOperation.delete(mFileInfo.getUrl(), mFileInfo.getId());is.close();}raf.close();connection.disconnect();} catch (Exception e) {e.printStackTrace();}}private void sendBroadcast(Intent intent,int progress){intent.putExtra("progress",progress);mContext.sendBroadcast(intent);}
}

三、源码地址

如果你觉得还不错,欢迎star或fork。
https://github.com/awenzeng/BreakPointDemo

四、参考文献

RandomAccessFiley详解
http断点续传原理:http头 Range、Content-Range
InputStream中read()与read(byte[] b)

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android断点续传

最近看了一些大佬去面试的时候都提到了断点续传&#xff0c;所以自己也写一个记录下来&#xff0c;断点续传的原理就是通过数据库实时的去保存当前下载的长度&#xff0c;然后下次再次下载的时候通过setRequestProperty告诉服务端我需要这个文件从什么地方开始下载&#xff0c;…

Android笔记--断点续传

断点续传就是在下载资源过程中&#xff0c;网络出现中断后&#xff0c;下一次下载的时候能够接着上一次下载的地方继续下载&#xff0c;以达到节省流量及时间的效果。在Http1.1协议中默认支持获取文件的部分内容&#xff0c;这其中主要是通过头部的两个参数:Range和Content Ran…

Linux断点续传

Linux断点续传 之前使用cp命令拷数据很慢&#xff0c;中途有一次服务器突然关机导致数据拷盘中断&#xff0c;后台发现了rsync命令后速度&#xff0c;工作效率大大提升了。rsync支持断点续传 断点续传测试&#xff1a; rsync -avzP --progress --rshssh /nfs1/public1 root1…

Android 多线程下载以及断点续传

多线程下载 在日常开发中&#xff0c;我们不可避免的会接到类似这样的需求&#xff0c;下载一个比较大的素材文件或者安装包文件&#xff0c;以此实现APP的自动更新&#xff0c;APP内的素材替换等。由于一般此类文件都比较大&#xff0c;一般会在50M以上&#xff0c;如果我们不…

断点续传的实现

文章目录 从上次断开位置继续下载实现原理&#xff08;客户端&#xff09;&#xff1a;HTTP实现&#xff08;流程&#xff09;&#xff1a;图1&#xff1a; 客户端 Range头部信息图2&#xff1a;服务端Content-Range信息 客户端与服务端的请求与响应图解&#xff1a;获取文件 E…

断点续传的原理

断点续传是大型文件数据传输的核心。本文将以多线程技术和Socket技术为依托&#xff0c;介绍大型文件断点续传的实现方法。  基本实现思想  多线程断点续传实现的基本思想就是在发送端&#xff08;也称客户端&#xff09;将要传输的文件分割为大小相当的多块&#xff0c;用…

wget 断点续传

wget是Linux系统中的一个下载工具&#xff0c;最近因为要下载一个比较大的数据集&#xff0c;直接使用浏览器下载每次断开后都会从头开始下载&#xff0c;而wget支持的断点续传功能则可以在已经下载的部分数据的基础上继续下载剩余数据。 &#xff08;1&#xff09;wget安装 …

如何实现文件断点续传功能

本文章首发于公众号攻城狮客栈&#xff0c;有需要的朋友可文末扫描二维码。 相信大家都使用过迅雷、电驴、百度云网盘等一类的工具&#xff0c;所有这些支持上传或下载的工具都有一个功能&#xff0c;那就是断点续传&#xff0c;也就是在你网络不佳传输断开时&#xff0c;传输会…

python 断点续传

python 断点续传 1.前序2.技术原理2.1 Content-Range2.2 Range 3. 代码实现 1.前序 当下载突然断开后&#xff0c;断点续传就需要了&#xff0c;继续前面下载的内容下载。解决了不需要重复下载 2.技术原理 HTTP/1.1 开始支持断点续传&#xff0c;一般断点下载会用到 Range 和…

web前端Tips:断点续传如何实现?

在Web前端中实现断点续传功能的一种常见方式是使用HTTP Range请求和文件分片上传。 以下是一个简单的断点续传实现的步骤&#xff1a; 前端将要上传的文件分成多个固定大小的片段&#xff08;chunk&#xff09;&#xff0c;例如每个片段的大小为1MB。当用户选择上传文件时&am…

前段实现文件的断点续传

早就听说过断点续传这种东西&#xff0c;前端也可以实现一下 断点续传在前端的实现主要依赖着HTML5的新特性&#xff0c;所以一般来说在老旧浏览器上支持度是不高的 本文通过断点续传的简单例子&#xff08;前端文件提交后端PHP文件接收&#xff09;&#xff0c;理解其大致的实…

Android开发——断点续传原理以及实现

0. 前言 在Android开发中&#xff0c;断点续传听起来挺容易&#xff0c;在下载一个文件时点击暂停任务暂停&#xff0c;点击开始会继续下载文件。但是真正实现起来知识点还是蛮多的&#xff0c;因此今天有时间实现了一下&#xff0c;并进行记录。本文原创&#xff0c;转载请注…

如何实现断点续传

断点续传是指在网络传输中&#xff0c;当传输过程中出现异常或者用户主动停止传输时&#xff0c;能够恢复传输过程&#xff0c;避免重新传输已经传输过的数据&#xff0c;提高传输效率。实现断点续传可以通过以下方式&#xff1a; HTTP协议支持的断点续传 在HTTP协议中&#xf…

【MQ学习笔记】RocketMQ知识分析与总结

RocketMQ 为什么使用mq&#xff1f;mq的作用&#xff1f;mq对你项目带来了什么&#xff1f;不选mq行不行&#xff1f; 异步&#xff0c;MQ能够以异步的方式对消息进行处理&#xff0c;能够大大提高了系统的响应以及吞吐量解耦&#xff0c;MQ双方只需要负责生产或消费信息即可…

销售数据分析方法、如何写好一个专题分析报告、Hive大数据知识体系教程、大数据分析平台总体架构方案……| 本周精华...

▲点击上方卡片关注我&#xff0c;回复“8”&#xff0c;加入数据分析领地&#xff0c;一起学习数据分析&#xff0c;持续更新数据分析学习路径相关资料~&#xff08;精彩数据观点、学习资料、数据课程分享、读书会、分享会等你一起来乘风破浪~&#xff09;回复“小飞象”&…

老杨刷完了23个跨年演讲,这6场最适合网工

晚上好&#xff0c;我是老杨。 放假放了一阵子&#xff0c;老杨闲着没事儿&#xff0c;一共刷了23个跨年演讲。 好的演讲&#xff0c;和一本好书一样&#xff0c;都是可以震荡灵魂的。 也知道最近大家都忙得很&#xff0c;这里推荐7个最值得一听的跨年演讲&#xff0c;贴心吧…

朱广权李佳琦直播掉线,1.2 亿人在线等

作者 | 胡巍巍 出品 | 程序人生&#xff08;ID&#xff1a;coder_life&#xff09; 原来央视爸爸也有掉线的时候。 4月6日晚间&#xff0c;“国民段子手”朱广权连麦李佳琦&#xff0c;给湖北做公益带货直播。 “小朱配琦”的神仙组合&#xff0c;让人大呼过瘾&#xff0c;该直…

“我让 AI 来处理我 24 小时的音频信息——这会是未来吗?”

整理 | 郑丽媛 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 这几年 AI 发展和进化的速度&#xff0c;几乎可以用三个字来形容&#xff1a;杀疯了。 AI 下棋、AI 编程、AI 作画、AI 写小说、AI 预测蛋白质结构……当 AI 逐渐融入我们的生活&#xff0c;你是否设…

抗住百万人直播、被联合国推荐,起底飞书技术演进之路!

你去公司上班了吗&#xff1f; 随着近期接连不断传来的好消息&#xff0c;上班族开始关心起这问题来。但许多企业在相关政策的号召下&#xff0c;仍采取远程办公的方式。据艾媒咨询的数据显示&#xff0c;今年春节期间中国远程办公企业规模超过 1800 万家&#xff0c;远程办公人…

听8位淘宝工程师聊聊他们眼中的元宇宙 | 1024特辑

我们是技术工作者&#xff0c;致力于思考和创新&#xff0c;用代码去解决生活中的问题&#xff0c;为消费者的快乐和幸福而努力。 今天是1024程序员节&#xff0c;我们邀请了8位不同岗位的淘宝工程师&#xff0c;聊了聊他们眼中的未来消费生活&#xff0c;他们眼中的元宇宙&…