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

Android Kotlin如何从Retrofit响应中下载图片并用FileOutputStream保存到设备

Kotlin 下载URL编码图片并通过FileOutputStream保存实现方案

注意:Android 10(API 29)及以上采用分区存储机制,保存到应用专属内部/缓存目录无需申请存储权限,保存到公共目录请适配MediaStore API,以下示例优先演示无权限要求的应用专属目录存储方案。

实现步骤

  • 第一步:解码URL编码的图片地址,你拿到的image_thumb字段是经过百分号编码的,需要先解码得到可访问的真实地址
  • 第二步:在子线程执行网络请求,禁止在主线程执行网络IO操作,推荐用Kotlin协程切换到IO调度器
  • 第三步:获取网络响应的输入流,通过FileOutputStream将流写入本地目标文件
  • 第四步:自动关闭流资源,Kotlin的use扩展函数会自动完成资源释放,无需手动调用close

完整代码示例

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient
import okhttp3.Request
import java.io.File
import java.io.FileOutputStream
import java.net.URLDecoder
import java.nio.charset.StandardCharsets

/**
 * 下载图片到本地应用缓存目录
 * @param encodedImageUrl 编码后的图片URL
 * @param saveFileName 保存的文件名,比如passport-307199094910Koala.jpg
 * @return 下载成功返回本地文件对象,失败返回null
 */
suspend fun downloadThumbImage(encodedImageUrl: String, saveFileName: String): File? = withContext(Dispatchers.IO) {
    // 解码URL编码的地址
    val validUrl = URLDecoder.decode(encodedImageUrl, StandardCharsets.UTF_8.name())
    // 构造本地保存文件
    val targetFile = File(applicationContext.cacheDir, saveFileName)
    val httpClient = OkHttpClient()
    val request = Request.Builder().url(validUrl).build()

    return@withContext runCatching {
        httpClient.newCall(request).execute().use { response ->
            if (!response.isSuccessful) return@runCatching null
            response.body?.use { body ->
                body.byteStream().use { inputStream ->
                    FileOutputStream(targetFile).use { outputStream ->
                        val buffer = ByteArray(8192)
                        var len: Int
                        while (inputStream.read(buffer).also { len = it } != -1) {
                            outputStream.write(buffer, 0, len)
                        }
                        outputStream.flush()
                    }
                }
            }
            targetFile
        }
    }.getOrNull()
}

调用说明

  • 该函数是挂起函数,需要在协程作用域中调用,例如viewModelScope、lifecycleScope
  • 如果你已经通过Retrofit配置了图片请求接口,可直接定义接口返回ResponseBody,拿到ResponseBody后直接取输入流写入FileOutputStream即可,无需重复创建OkHttpClient
  • 若需要保存到公共下载目录供其他应用访问,Android 10及以上请使用MediaStoreAPI创建文件写入,不要直接使用公共目录的File路径

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 08:36:05