OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围:

实现原理

  1. Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes=1024-

  2. 本地文件记录:保存已下载的字节位置

  3. 206 状态码处理:服务器返回部分内容(HTTP 206 Partial Content)

  4. 文件追加写入:从上次中断的位置继续写入文件

完整实现代码(Kotlin/Java)

kotlin

import okhttp3.*
import java.io.File
import java.io.IOException
import java.io.RandomAccessFileclass ResumeDownloader(private val client: OkHttpClient = OkHttpClient()
) {fun download(url: String, file: File, listener: ProgressListener? = null) {// 1. 获取已下载字节数val downloadedBytes = if (file.exists()) file.length() else 0L// 2. 创建带Range头的请求val request = Request.Builder().url(url).header("Range", "bytes=$downloadedBytes-").build()client.newCall(request).enqueue(object : Callback {override fun onFailure(call: Call, e: IOException) {listener?.onError(e)}override fun onResponse(call: Call, response: Response) {if (!response.isSuccessful) {listener?.onError(IOException("Unexpected code: ${response.code}"))return}// 3. 检查服务器是否支持断点续传val isResumeSupported = response.code == 206 // Partial Contentval totalBytes = response.header("Content-Length")?.toLongOrNull() ?: -1Lval finalTotalBytes = if (isResumeSupported) {downloadedBytes + (totalBytes)} else {totalBytes}// 4. 处理响应体response.body?.use { body ->RandomAccessFile(file, "rw").use { output ->// 移动到文件末尾追加output.seek(downloadedBytes)val input = body.byteStream()val buffer = ByteArray(8192)var bytesRead: Intvar progress = downloadedBytes// 5. 写入文件while (input.read(buffer).also { bytesRead = it } != -1) {output.write(buffer, 0, bytesRead)progress += bytesRead// 更新进度listener?.onProgress(progress, finalTotalBytes)}listener?.onComplete(file)}}}})}interface ProgressListener {fun onProgress(currentBytes: Long, totalBytes: Long)fun onComplete(file: File)fun onError(e: Exception)}
}

Java 版本核心代码

java

// 创建带Range头的请求
long downloadedBytes = file.length();
Request request = new Request.Builder().url(url).addHeader("Range", "bytes=" + downloadedBytes + "-").build();// 处理响应
try (Response response = client.newCall(request).execute()) {if (response.code() == 206) { // Partial Contenttry (RandomAccessFile output = new RandomAccessFile(file, "rw");InputStream input = response.body().byteStream()) {output.seek(downloadedBytes);byte[] buffer = new byte[8192];int bytesRead;while ((bytesRead = input.read(buffer)) != -1) {output.write(buffer, 0, bytesRead);}}}
}

关键注意事项

  1. 服务器支持检查

    • 成功时返回 HTTP 206(部分内容)

    • 失败时返回 200(完整文件)或 416(范围请求错误)

    • 响应头需包含 Accept-Ranges: bytes

  2. 文件处理

    • 使用 RandomAccessFile 实现文件随机访问

    • 通过 seek() 定位到文件末尾

    • 避免覆盖已下载内容

  3. 进度跟踪

    • 总大小 = 已下载大小 + Content-Length

    • 实时计算:currentBytes += bytesRead

  4. 异常处理

    • 网络中断时保存当前进度

    • 重新下载时使用最新文件长度

增强功能建议

  1. 进度持久化:使用数据库记录下载状态

  2. 暂停/恢复:暴露下载控制接口

  3. 多线程下载:分割文件范围并行下载(需服务器支持)

  4. 完整性校验:下载完成后验证文件 MD5/SHA1

示例用法:

kotlin

val downloader = ResumeDownloader()
val file = File(context.filesDir, "largefile.zip")downloader.download("https://example.com/largefile.zip", file,object : ResumeDownloader.ProgressListener {override fun onProgress(current: Long, total: Long) {val percent = (current * 100 / total).toInt()updateProgressBar(percent)}override fun onComplete(file: File) {showToast("下载完成")}override fun onError(e: Exception) {showError(e.message)}}
)

通过此实现,OkHttp 可在网络中断后自动从断点恢复下载,大幅提升大文件下载体验。

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

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

相关文章

函数中的Callable

在编程中,​Callable(可调用对象)​​ 是指任何可以通过 () 操作符调用的对象。在函数和类设计的上下文中,Callable 通常指代可以被调用的实体,例如函数、方法、Lambda表达式或实现了 __call__ 方法的对象。以下是详细…

MySQL学习之触发器

文章目录 前言什么是触发器(Trigger)?触发器的特点 MySQL中触发器的用法创建NEW 与 OLD举例其他操作 注意事项后续内容参考目录 前言 阅读本文前请注意最后编辑时间,文章内容可能与目前最新的技术发展情况相去甚远。欢迎各位评论…

AIGC 基础篇 Python基础 04 for循环与while循环

今天,我们来讲Python里面的循环部分 1.for循环 for i in range(1,10,2):print(i) 这是一个简单但是完整的for循环,里面包含了for循环的所有结构 首先注意格式是“for 变量 in range(取得到的起始值,取不到的终点值,步长)” …

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…

每日算法 -【Swift 算法】三数之和最接近目标值

🚀 Swift 实现:三数之和最接近目标值(3Sum Closest) ✨ 前言 在算法学习过程中,经典的“三数之和”系列题目是很多人通往进阶路上的一道坎。今天我们来介绍其中一个非常实用的变种问题 —— 三数之和最接近目标值(3Sum Closest),并使用 Swift 实现一个高效的解法。 …

python打卡day50@浙大疏锦行

知识点回顾: resnet结构解析CBAM放置位置的思考针对预训练模型的训练策略 差异化学习率三阶段微调 ps:今日的代码训练时长较长,3080ti大概需要40min的训练时长 作业: 好好理解下resnet18的模型结构尝试对vgg16cbam进行微调策略 R…

虚幻引擎5-Unreal Engine笔记之SET节点的输出引脚获取设置后的最新变量值

虚幻引擎5-Unreal Engine笔记之SET节点的输出引脚获取设置后的最新变量值 code review! 一个变量的“SET”节点 retrieve 是动词,意思是“检索、获取、取回”。 retrieves 只是当主语是第三人称单数(比如 he、she、it 或单个人/物)时使用的…

编译原理实验 之 TINY 解释测试目标代码

文章目录 实验任务1任务2 本次的实验是在前三次TINYC的基础上的一个测试,所以完成前三次的实验是基础 编译原理 之 实验一 编译原理实验 之 Tiny C语言编译程序实验 语法分析 编译原理实验 之 TINY 之 语义分析(第二次作业 首先将新的文件复制到先前的…

CanFestival移植到STM32G4

文章目录 一、准备工作二、软件配置三、移植CanFestival参考 一、准备工作 1、获取Canfestival源码 2、Python下载 3、wxPython下载 4、CanFestival字典生成 5、安装参考 Python2.7.15及wxPython2.8百度云盘下载地址:https://pan.baidu.com/s/1bRS403m4B31m4ovSJ-_…

iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈

在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…

第十三章 RTC 实时时钟

第十三章 RTC 实时时钟 目录 第十三章 RTC 实时时钟 1 RTC简介 1.1 主要特性 2 功能描述 2.1 概述 2.2 复位过程 2.3 读RTC寄存器 2.4 配置RTC寄存器 2.5 RTC标志的设置 3 RTC寄存器描述 3.1 RTC控制寄存器高位(RTC_CRH) 3.2 RTC控制寄存器低位(RTC_CRL) 3.3 RTC预…

618来了,推荐京东云服务器

2核2G3M,49元/1年,348元/3年 2核4G5M,149元/1年,518元/3年 4核8G5M,368元/1年,1468元/3年 8核16G5M,1258元/1年,3498元/3年 8核32G10M,1498元/1年,4268元/3年 活动地址:https://3.cn/2hT-F6AX

数据库逻辑删除,唯一性约束究极解决方案

文章目录 一、写在前面二、解决方案1、业务逻辑层面控制2、物理删除数据归档3、is_delete !0的都认为是删除(推荐)4、MySQL 函数索引(表达式索引)(需 MySQL 8.0)(推荐)5、部分索引&a…

3-存储系统

一-基本概念 二-主存储器 三-主存储器与CPU的连接 四-外部存储器 五-高速缓冲存储器 六-虚拟存储器

华为0528笔试

第三题 题目 给定一个二维数组 mountainMap 表示一座山的地图,数组中的每个元素 mountainMap[x][y] 代表坐标 (x, y) 处山的高度。登山员从山底出发,爬到山峰。 山底的含义:mountainMap中高度为0的坐标点。 山峰的含义:mountain…

Redis的过期策略和淘汰策略

Redis的过期策略和淘汰策略 想象一下周末的大型超市:生鲜区的酸奶贴着"今日特价"标签,促销员定时检查这些商品的保质期;而仓库管理员正根据"先进先出"原则整理货架,确保商品不会过期积压。这种高效的商品管理…

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …

【HarmonyOS 5】 影视与直播详以及 开发案例

&#x1f3a5; ‌一、超高清低延迟直播‌ ‌4K/8K硬解能力‌&#xff1a;通过鸿蒙媒体引擎实现15Mbps码率视频流稳定解码&#xff0c;华为Pura X实测端到端延迟<80ms‌分布式渲染‌&#xff1a;支持手机拍摄→智慧屏导播→平板监看的工作流协同&#xff0c;设备间传输延迟&…

Tunna工具实战:基于HTTP隧道的RDP端口转发技术

工具概述 Tunna是一款利用HTTP/HTTPS隧道进行TCP通信的渗透测试工具&#xff0c;由SECFORCE团队开发并开源。该工具主要应用于需要绕过防火墙限制的场景&#xff0c;通过Webshell实现内网服务的端口转发&#xff0c;特别适合在仅开放80/443端口的环境中建立TCP连接。 项目地址…

c# Autorest解析

AutoRest 工具生成用于访问 RESTful Web 服务的客户端库。AutoRest 的输入是使用 OpenAPI 规范格式描述 REST API 的规范。OpenAPI(f.k.a Swagger)规范代码生成器。支持 C#、PowerShell、Go、Java、Node.js、TypeScript、Python。 安装 AutoRest 在 Windows、MacOS 或 Linux …