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

Kotlin中使用URLConnection下载文件时文件大小异常(16MB图片仅保存84B)的原因排查

问题分析与修复方案

嘿,我看了你的代码,这84B的文件大概率是两个核心原因导致的:要么你下载的根本不是图片数据,要么是写入文件的逻辑被意外跳过了,咱们一步步来捋清楚:

1. 最致命的坑:写入逻辑被Content-Disposition判断挡住了

你代码里读取输入流并写入文件的核心逻辑,完全包裹在if (disposition != null)的代码块中:

if (disposition != null) {
    // 解析文件名的逻辑
    // ...
    // 读取流、写文件的核心代码全在这里!
    `is` = conn.inputStream
    os = FileOutputStream(File(outputDir, fileName))
    // ...写文件的循环
}

如果你的服务器没有返回Content-Disposition这个响应头,那这段写文件的代码根本不会执行!但你可能还是创建了空文件,或者不小心写入了少量日志内容,这就解释了为什么文件只有84B。

修复方法:把写文件的逻辑抽出来,不管有没有Content-Disposition都执行,同时给文件名设置一个默认值:

// 先处理文件名,没有disposition就用默认名兜底
var fileName = "user_sign.jpg"
if (disposition != null) {
    val target = "filename="
    val index = disposition.indexOf(target)
    if (index != -1) {
        fileName = disposition.substring(index + target.length).replace("\"", "")
    }
    println("Content-Type = $contentType")
    println("Content-Disposition = $disposition")
    println("fileName = $fileName")
}
// 把写文件的逻辑移到外面,确保一定会执行
`is` = conn.inputStream
os = FileOutputStream(File(outputDir, fileName))
val BUFFER_SIZE = 4096
var bytesRead: Int
val buffer = ByteArray(BUFFER_SIZE)
while (`is`.read(buffer).also { bytesRead = it } != -1) {
    os.write(buffer, 0, bytesRead)
}
// 别忘了关闭流(或者用Kotlin的use函数自动关闭更安全)
os.close()
`is`.close()

2. 请求头设置错误:你告诉服务器只接受JSON,但要下载的是图片

你设置了Accept: application/json:

conn.setRequestProperty("Accept", "application/json")

这相当于明确告诉服务器:"我只想要JSON格式的数据",服务器可能直接返回了一段JSON错误信息(比如"请求格式不匹配"),而不是图片——这84B很可能就是这段JSON的大小!

修复方法:把Accept头改成接受图片类型,或者用通用类型兼容所有情况:

// 只接受图片类型,更精准
conn.setRequestProperty("Accept", "image/*")
// 或者用通用类型,接受所有响应格式
// conn.setRequestProperty("Accept", "*/*")

3. 几个额外的优化建议

  • 你的连接超时只有1.5秒,对于16MB的图片来说大概率会超时,建议延长超时时间:
    conn.connectTimeout = 10000 // 10秒连接超时
    conn.readTimeout = 10000 // 加上读取超时,防止读取数据时卡住
    
  • 用Kotlin的use函数自动管理流资源,避免手动关闭时的异常泄漏:
    conn.inputStream.use { inputStream ->
        FileOutputStream(File(outputDir, fileName)).use { outputStream ->
            val buffer = ByteArray(4096)
            var bytesRead: Int
            while (inputStream.read(buffer).also { bytesRead = it } != -1) {
                outputStream.write(buffer, 0, bytesRead)
            }
        }
    }
    
  • 可以先把输入流转成字符串打印出来,看看那84B到底是什么内容——如果是JSON,直接就能知道服务器为啥没返回图片了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 19:07:44