You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用OkHttp下载文件频繁触发SocketTimeoutException问题排查

问题分析与解决方案

首先,我完全懂你此刻的困惑——文件明明已经完整下载到SD卡了,可writeResponseBodyToDisk方法却因为java.net.SocketTimeoutException返回false,这个问题确实和服务器未返回contentLength(值为-1)以及你的OkHttp超时配置直接相关,咱们一步步拆解解决:

核心原因

1. 缺失readTimeout配置

你当前只给OkHttpClient设置了connectTimeout和writeTimeout(均为60秒),但完全没配置readTimeout!OkHttp默认的readTimeout是10秒,当服务器不返回contentLength时,OkHttp没法预知要读取多少数据,会一直从流里读直到结束。如果下载过程中(尤其是大文件或网络波动时),两次数据传输的间隔超过10秒,就会触发超时异常——哪怕文件最后已经完整写入磁盘,这个异常还是会在读取阶段抛出,导致方法返回false。

2. 进度计算的潜在bug

你用percent = (int) (100.0f * (float) downloadSize / totalSize)计算下载进度,但totalSize因为服务器没返回contentLength而无效(大概率是0),这会导致进度计算错误(比如触发除以0的情况),虽然这不是超时的直接原因,但会影响下载状态的正常反馈。

具体解决方案

1. 补充readTimeout配置

在OkHttpClient.Builder里加上readTimeout,建议设置和connect、write相同的时长(或更长,根据你的文件大小和网络环境调整):

private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder()
        .connectTimeout(60, TimeUnit.SECONDS)
        .writeTimeout(60, TimeUnit.SECONDS)
        .readTimeout(60, TimeUnit.SECONDS); // 新增这一行

这会让OkHttp在等待数据时拥有足够的超时窗口,避免因为服务器未返回contentLength而提前触发超时异常。

2. 修复进度计算逻辑

因为服务器没返回文件大小,totalSize无效,所以要调整进度计算逻辑,避免无效运算:

// 替换原来的percent计算代码
if (totalSize > 0) {
    percent = (int) (100.0f * (float) downloadSize / totalSize);
} else {
    // 服务器未返回文件大小,可设置为-1表示无法计算进度,或者给用户显示“正在下载中”
    percent = -1;
}

3. 优化超时异常的特殊处理

在writeResponseBodyToDisk方法中,你可以单独捕获SocketTimeoutException,额外判断文件是否已经完整写入(比如对比文件实际大小和downloadSize,或者尝试打开文件验证完整性),如果文件确实完整,就返回true而非直接返回false:

catch (SocketTimeoutException e) {
    Log.i(TAG, "Download timed out, checking file integrity...");
    // 这里可以添加文件完整性校验逻辑,比如检查文件是否存在且大小匹配下载的字节数
    if (file.exists() && file.length() == downloadSize) {
        return true;
    }
    Log.i(TAG, "File integrity check failed: " + e.toString());
    return false;
}

为什么文件已下载却抛出异常?

这种情况通常是服务器在传输完所有文件数据后,没有及时关闭连接,OkHttp会继续等待更多数据,直到超过readTimeout时长后抛出异常。此时文件已经通过输出流完整写入磁盘,但异常会触发方法返回false,让你误以为下载失败。

内容的提问来源于stack exchange,提问作者Ehsan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:12:45