使用OkHttp下载PDF至Android设备后文件大小为0的问题
解决OkHttp下载PDF文件大小为0的问题
你遇到的情况很典型——代码只创建了空文件,但完全没把服务器返回的PDF内容写入文件,这就是文件大小为0的核心原因。咱们来一步步修复这个问题:
问题根源分析
你的onResponse方法里仅完成了打印日志、创建空文件这两步,漏掉了最关键的操作:读取响应体的字节流并写入到目标文件中。另外还要注意,不能直接认为进入onResponse就是成功响应,得先判断HTTP状态是否正常,避免处理错误响应的空body。
修复后的完整回调代码
client.newCall(request).enqueue(object : Callback { override fun onFailure(call: Call, e: IOException) { println("下载失败:${e.message}") } override fun onResponse(call: Call, response: Response) { // 先校验响应是否为成功状态(HTTP 200-299) if (!response.isSuccessful) { println("响应异常:${response.code} ${response.message}") response.close() // 务必关闭响应体,避免资源泄漏 return } // 处理响应体,用use自动关闭流,无需手动写try-finally response.body?.use { body -> val file = File(filesDir, "Test.pdf") try { // 将响应体字节写入文件 file.outputStream().use { outputStream -> outputStream.write(body.bytes()) println("下载完成!文件大小:${file.length()}字节") } } catch (e: IOException) { println("写入文件失败:${e.message}") } } ?: run { println("响应体为空,无法写入文件") response.close() } } })
关键细节补充
如果你的PDF文件体积较大,上面的body.bytes()会把整个文件加载到内存中,可能导致内存溢出。这种情况下推荐用逐块写入的方式,降低内存占用:
response.body?.use { body -> val file = File(filesDir, "Test.pdf") file.outputStream().use { outputStream -> body.source().use { source -> val buffer = Buffer() // 每次读取8KB块写入文件 while (source.read(buffer, 8192) != -1) { outputStream.write(buffer.readByteArray()) } } println("大文件下载完成,大小:${file.length()}字节") } }
额外提示
OkHttp的enqueue回调是在子线程执行的,所以这里的文件写入操作不会阻塞主线程,无需额外开线程处理。另外filesDir是App的内部存储路径,不需要申请外部存储权限,直接使用即可。
内容的提问来源于stack exchange,提问作者Scooter
相关产品推荐
相关产品推荐

