使用Retrofit下载文件后无法正常打开的问题排查请求
Retrofit下载文件后无法正常打开:图片黑屏/文件格式错误排查
问题描述:使用Retrofit下载文件时,日志显示下载完成且大小匹配,但打开文件时图片显示黑屏,其他文件提示格式错误。
文件创建代码
val file = File(getExternalFilesDir(null), event.fileName)
ResponseBody写入磁盘代码
private fun writeResponseBodyToDisk(body: ResponseBody, file: File): Boolean { return try { // todo change the file location/name according to your needs val futureStudioIconFile: File = file var inputStream: InputStream? = null var outputStream: OutputStream? = null try { val fileReader = ByteArray(4096) val fileSize: Long = body.contentLength() var fileSizeDownloaded: Long = 0 inputStream = body.byteStream() outputStream = FileOutputStream(futureStudioIconFile) while (true) { val read: Int = inputStream.read(fileReader) if (read == -1) { break } outputStream.write(fileReader, 0, read) fileSizeDownloaded += read.toLong() Timber.d("%s%s", "file download: $fileSizeDownloaded of ", fileSize) } outputStream.flush() viewState.value = ViewState.ShowFile(file) true } catch (e: IOException) { false } finally { inputStream?.close() outputStream?.close() } } catch (e: IOException) { false } }
文件查看代码
val fileUri = FileProvider.getUriForFile( this, "${BuildConfig.APPLICATION_ID}.fileprovider", state.file ) startActivity( Intent.createChooser( Intent().apply { action = Intent.ACTION_VIEW putExtra(Intent.EXTRA_STREAM, fileUri) clipData = ClipData.newRawUri("", fileUri) type = "*/*" addFlags( Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION ) }, null ) )
下载日志
file download: 4096 of 21688 file download: 8192 of 21688 file download: 12288 of 21688 file download: 16384 of 21688 file download: 20480 of 21688 file download: 21688 of 21688
排查方向
- 检查Retrofit接口配置:确保接口返回
ResponseBody时,添加@Streaming注解,且该接口未被Gson等JSON转换器处理。如果未加@Streaming,大文件可能被缓存到内存导致写入数据损坏。 - 验证文件完整性:将下载后的文件传到电脑,对比原文件的MD5/SHA哈希值。若不匹配,说明写入过程存在问题:
- 写入前先调用
file.delete()清空旧文件,避免残留数据干扰; - 改用Kotlin的
use函数自动管理流,替代手动循环,减少出错概率:body.byteStream().use { inputStream -> FileOutputStream(file).use { outputStream -> inputStream.copyTo(outputStream, bufferSize = 4096) } }
- 写入前先调用
- 检查响应压缩处理:查看服务器响应头是否包含
Content-Encoding: gzip,如果有,需给OkHttp添加Gzip解压拦截器,否则写入的是压缩后的二进制数据,导致格式错误。 - 修正文件查看Intent:
- 替换
EXTRA_STREAM为data字段传递Uri; - 不要使用
*/*,通过ContentResolver获取准确的MIME类型,让系统选择正确的应用打开文件:private fun getMimeType(file: File): String? { return contentResolver.getType(Uri.fromFile(file)) }
- 替换
- 确认文件扩展名:检查
event.fileName是否包含正确的扩展名(如.jpg、.pdf),无扩展名会导致系统无法识别文件类型。
内容的提问来源于stack exchange,提问作者Nikita Vasko
相关产品推荐
相关产品推荐

