java异常处理不直接触发断点续传,而是通过捕获网络超时、连接失败、http响应异常等中断场景保障状态持久化;进度必须在数据写入磁盘后立即保存,启动时以文件实际长度为准恢复offset。

Java 中异常处理本身不直接触发断点续传,它的作用是保障断点续传逻辑的可靠性:当下载中断(如网络超时、连接断开、IO失败)时,异常捕获能防止程序崩溃,并确保已写入的数据和当前进度不丢失,为下次恢复提供依据。
关键在于:断点续传靠的是状态持久化,不是靠“捕获异常才开始续传”。异常处理只是兜底机制。
下面从实际协作角度说明怎么配合使用:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
异常捕获要覆盖三类典型中断场景
网络超时
HttpURLConnection或HttpClient设置合理超时后,抛出SocketTimeoutException或java.net.SocketTimeoutException
→ 记录当前 offset,休眠后重试,不更新进度文件连接失败
如 DNS 解析失败、目标服务器拒绝连接,抛出UnknownHostException、ConnectException
→ 暂停几秒(如 2–5 秒),再尝试建立连接,offset 不变-
HTTP 响应异常
- 返回
416 Requested Range Not Satisfiable:说明文件已下完,可清理.progress文件并退出 - 返回
5xx或非200/206状态码:记录错误,等待后重试 -
InputStream.read()返回-1或抛出IOException:说明数据流提前结束,需校验文件大小是否匹配预期
- 返回
状态保存必须独立于异常发生时机
- 每次成功写入一块数据(例如用
RandomAccessFile.write()或FileOutputStream.write()写完 buffer)后,立刻把当前总字节数写入.progress文件 - 推荐做法:
try (RandomAccessFile raf = new RandomAccessFile(file, "rw")) { raf.seek(offset); raf.write(chunk); // ✅ 数据落盘后立即更新进度 updateProgressFile(offset + chunk.length); } - 绝对不要在发请求前、或收到响应头后就更新进度——此时数据还没真正写进磁盘,进程崩溃就会丢进度
下载启动时先恢复状态
- 每次开始下载前,先读取
.progress文件获取startOffset - 同时调用
file.length()获取本地文件实际大小 - 若两者不一致(常见于异常中断后未及时更新
.progress),以file.length()为准(更可信) - 构造
Range: bytes=<startoffset>-</startoffset>请求头,打开文件始终用"rw"或"rwd"模式(保证写入同步)
一个轻量但可靠的重试+恢复结构示意
long offset = loadProgress(); // 从 .progress 或 file.length() 获取
while (offset 0) {
raf.write(buffer, 0, n);
offset += n;
saveProgress(offset); // ✅ 成功写入后立刻落盘
}
}
} else if (conn.getResponseCode() == 416) {
break; // 已完成
}
} catch (SocketTimeoutException | ConnectException e) {
log.warn("网络异常,暂停3秒后重试,当前 offset: {}", offset);
Thread.sleep(3000);
// offset 不变,继续循环
} catch (IOException e) {
log.error("IO 错误", e);
Thread.sleep(1000);
}
}
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










