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

Android Marshmallow以上版本Retrofit 2 Multipart API报错问题

解决Retrofit 2 Multipart在Android Marshmallow+设备抛出的IllegalStateException问题

我之前也碰到过一模一样的情况,这个问题的核心其实和Android 6.0开始的动态权限机制脱不了干系,当然也可能和文件本身的有效性有关,咱们一步步拆解:

问题根源

  • 动态权限缺失:Android 6.0(API 23)起,读取外部存储的权限(READ_EXTERNAL_STORAGE)属于危险权限,必须在运行时主动申请,光靠Manifest声明没用。如果你的App在Marshmallow+设备上没拿到这个权限,代码里File file = new File(filePaths.get(i))不会直接报错,但后续尝试读取文件(比如创建RequestBody、获取文件信息)会失败,导致循环里根本没往MultipartBody.Builder里添加任何part,最后build时就会抛出Multipart body must have at least one part的异常。
  • 无效文件路径:也有可能是部分文件路径在高版本系统中受限于Scoped Storage无法访问,或者文件本身已被删除,导致循环中没有有效文件被添加到builder中。

解决方案

1. 先确保拿到动态权限

在执行上传逻辑前,先检查并申请存储权限:

// 检查是否已获取存储权限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
        != PackageManager.PERMISSION_GRANTED) {
    // 弹出权限申请对话框
    ActivityCompat.requestPermissions(this,
            new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
            REQUEST_STORAGE_PERMISSION_CODE);
    return;
}
// 权限已获取,执行上传
uploadFiles(filePaths);

2. 校验文件有效性,避免空part

循环添加文件前,先检查文件是否存在且为有效文件:

MultipartBody.Builder builder = new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);

try {
    for (int i = 0; i < filePaths.size(); i++) {
        File file = new File(filePaths.get(i));
        // 先校验文件有效性
        if (file.exists() && file.isFile() && file.length() > 0) {
            String mFileName = App.getInstance().getPrefs().getUserId() + "_" + new Date().getTime() + "_" + i;
            // 添加文件part到builder
            builder.addFormDataPart("files[]", mFileName,
                    RequestBody.create(MediaType.parse("multipart/form-data"), file));
        }
    }
} catch (Exception e) {
    e.printStackTrace();
}

// 兜底检查:确保builder至少有一个part再提交请求
MultipartBody requestBody = builder.build();
if (requestBody.parts().isEmpty()) {
    // 提示用户没有可上传的有效文件
    Toast.makeText(this, "未找到可上传的有效文件", Toast.LENGTH_SHORT).show();
    return;
}

// 继续执行Retrofit请求逻辑
// ...

3. 适配Android 10+的Scoped Storage

如果你的App面向Android 10(API 29)及以上版本,直接通过文件路径访问外部存储可能会受限,建议使用MediaStore或存储访问框架(SAF)来获取文件,避免路径无效的问题。

总结

这个问题本质是高版本Android权限和存储机制变化导致的,只要确保权限到位、文件有效,再加上兜底检查,就能解决这个异常啦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:46:54