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
相关产品推荐
相关产品推荐

