OkHttp写入磁盘时遇网络中断致文件残缺,如何规避连接占用?
OkHttp3 下载文件时避免写入磁盘阶段网络连接保持的问题
问题核心解答
OkHttp 在执行 sink.writeAll(response.body().source()) 写入磁盘的过程中,确实会保持HTTP连接处于打开状态。因为 response.body().source() 直接绑定到网络输入流,写入操作是边从网络读取数据、边写入磁盘的过程,直到所有数据传输完成前,网络连接都会维持活跃状态。一旦中途网络断开,写入操作会直接中断,导致磁盘上留下不完整的文件。
解决方案
根据文件大小的不同,有两种可靠的处理方式:
1. 小文件:先读入内存,再写入磁盘
如果下载的文件体积较小(不会触发内存溢出),可以先将所有数据一次性读入内存,关闭OkHttp的响应(释放网络连接)后,再写入磁盘。这样写入磁盘时网络连接已经关闭,不会受网络波动影响。
示例代码:
Response response = client.newCall(request).execute(); try { // 一次性读取全部响应数据到内存 byte[] fileData = response.body().bytes(); // 立即关闭响应,释放网络连接 response.close(); // 将内存中的数据写入目标文件 File targetFile = MyFileManager.getMyFile(context); BufferedSink sink = Okio.buffer(Okio.sink(targetFile)); sink.write(fileData); sink.close(); } catch (IOException e) { // 处理读取或写入异常 e.printStackTrace(); } finally { // 确保响应最终被关闭,避免资源泄漏 if (response != null && !response.isClosed()) { response.close(); } }
2. 大文件:使用临时文件中转
如果文件体积较大,直接读入内存会导致OOM,建议先将数据写入临时文件,确认全部数据下载完成后,再将临时文件原子性地移动到目标位置。这样即使中途网络错误,只会生成不完整的临时文件,不会影响目标文件的完整性。
示例代码:
Response response = client.newCall(request).execute(); File targetFile = MyFileManager.getMyFile(context); // 创建临时文件,避免直接写入目标文件 File tempFile = new File(targetFile.getParent(), targetFile.getName() + ".tmp"); BufferedSink sink = null; try { sink = Okio.buffer(Okio.sink(tempFile)); // 完成全部数据写入临时文件(此阶段网络连接仍保持,但异常时只会影响临时文件) sink.writeAll(response.body().source()); sink.close(); // 关闭响应,释放网络连接 response.close(); // 原子性移动临时文件到目标位置(系统级操作,不会中断) boolean renameSuccess = tempFile.renameTo(targetFile); if (!renameSuccess) { throw new IOException("Failed to move temp file to target path"); } } catch (IOException e) { // 发生异常时删除临时文件,避免垃圾文件残留 if (tempFile.exists()) { tempFile.delete(); } e.printStackTrace(); } finally { // 确保资源被释放 if (sink != null) { try { sink.close(); } catch (IOException e) { e.printStackTrace(); } } if (response != null && !response.isClosed()) { response.close(); } }
关键注意事项
- 无论哪种方案,都必须确保在操作完成后调用
response.close(),避免网络连接资源泄漏。 - 使用临时文件方案时,
renameTo操作在大多数文件系统中是原子性的,能保证目标文件要么完整存在,要么不存在,不会出现中间状态。
内容的提问来源于stack exchange,提问作者Steve
相关产品推荐
相关产品推荐

