Kotlin Retrofit多部分上传图片遇End of Input异常求助
先排查服务器端响应问题
上传进度到100%说明请求已经完整发送到服务器,"End of Input"异常大多是因为服务器没有返回合法的响应体——可能是服务器内部报错后没有输出任何内容,或者返回了空响应。你可以用Postman或者Charles模拟一次相同的图片上传,看看服务器的返回结果:如果模拟上传也报错,那问题出在服务器端;如果模拟正常,再回头排查客户端代码。检查Retrofit接口定义是否匹配服务器返回
如果服务器在上传成功后没有返回任何响应体(只返回状态码),但你的接口定义了要解析某个实体类,就会触发这个异常。比如把接口返回类型从Call<UploadResponse>改成Call<Void>或者Response<Void>,让Retrofit不要尝试解析空响应体:@Multipart @POST("upload") fun uploadImage(@Part file: MultipartBody.Part): Call<Void>后续回调里只需要判断响应码是否在200-299区间即可确认上传成功。
确保正确读取图片URI对应的文件流
相机拍摄的图片URI通常是content://类型,不能直接用File(uri.path)获取文件(这个路径不是真实文件路径),要通过ContentResolver打开输入流:val inputStream = contentResolver.openInputStream(imageUri) ?: throw IOException("无法读取图片文件") val requestBody = inputStream.use { RequestBody.create(MediaType.parse("image/jpeg"), it.readBytes()) } val imagePart = MultipartBody.Part.createFormData("file", "captured_image.jpg", requestBody)用
use函数可以自动管理流的生命周期,避免流提前关闭导致上传数据不完整(不过进度到100%说明数据发完了,但这个步骤还是要确保正确)。添加日志拦截器查看完整请求响应
给OkHttpClient加上HttpLoggingInterceptor,打印出完整的请求头、请求体和响应内容,能帮你明确服务器到底返回了什么:val loggingInterceptor = HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY } val okHttpClient = OkHttpClient.Builder() .addInterceptor(loggingInterceptor) .build()然后把这个client传入Retrofit的Builder里,查看Logcat里的响应日志,如果显示响应体为空,就对应调整接口的返回类型。
检查RequestBody的MediaType配置
确保设置的MediaType和图片格式一致,比如JPG用"image/jpeg",PNG用"image/png",错误的MediaType可能导致服务器无法处理请求,进而返回空响应。另外文件名尽量不要包含特殊字符,避免服务器解析表单时出错。
内容的提问来源于stack exchange,提问作者JT Lai

