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

使用Retrofit2上传图片与数据无回调响应,该如何解决?

Retrofit2 Multipart请求无响应:既不进入onResponse也不进入onFailure

我在Postman中可以正常上传指定数据,但用Retrofit2编写的代码出现了问题:调试时流程正常,但执行到call.enqueue()后,既不进入onResponse也不进入onFailure,直接走到方法末尾,请求毫无反应。以下是我的代码:

客户端创建

public BeeMappingClient(String url){
    retrofit= new Retrofit.Builder()
        .baseUrl(url)
        .addConverterFactory(ScalarsConverterFactory.create())
        .addConverterFactory(GsonConverterFactory.create())
        .build();
    conexion=retrofit.create(Conexion.class);
}

接口定义

@Multipart
@POST("task")
Call<ResponsetTask> API_Task(@Header("Authorization") String key, 
                            @Part MultipartBody.Part multipartImage, 
                            @Part("message") RequestBody message , 
                            @Part("filecomment") RequestBody filecomment, 
                            @Part("api_token") RequestBody api_token, 
                            @Part("user_id") RequestBody user_id);

请求调用

File file=new File(path);
MultipartBody.Part[] multipartImageList = new MultipartBody.Part[1];
RequestBody surveyBody = RequestBody.create(MediaType.parse("image/*"), file);
multipartImageList[0] = MultipartBody.Part.createFormData("image", "image.jpg", surveyBody);
RequestBody message = RequestBody.create(MediaType.parse("message"), Constantes.MESSAGE);
RequestBody filecomment = RequestBody.create(MediaType.parse("filecomment"), Constantes.FILECOMMENT);
RequestBody api_token = RequestBody.create(MediaType.parse("api_token"),Constantes.api_token);
RequestBody user_id = RequestBody.create(MediaType.parse("user_id"), Integer.toString(Constantes.id));
Call<ResponsetTask> call = conexion.API_Task(Constantes.AUTH,multipartImageList[0],message,filecomment,api_token,user_id);
call.enqueue(new Callback<ResponsetTask>() {
    @Override
    public void onResponse(Call<ResponsetTask> call, Response<ResponsetTask> response) {
        Constantes.api_task=response.body().getTaskId();
    }
    @Override
    public void onFailure(Call<ResponsetTask> call, Throwable t) {
    }
});

请问该如何解决?当前上传方式是否最优?感谢帮助。


这种情况我之前做项目的时候也碰到过,Postman能正常跑但Retrofit没回调,大概率是代码里的几个细节没处理好,咱们一步步来解决:

一、排查无响应的核心原因

1. 非文件参数的MediaType设置错误

你给message、filecomment这些普通字符串参数设置的MediaType是参数名本身(比如MediaType.parse("message")),这是错误的!服务器无法识别这种自定义的MediaType,可能导致请求卡住或无法被正确解析,进而回调不触发。

修正方式:把非文件参数的MediaType改成标准的文本类型,比如text/plain:

RequestBody message = RequestBody.create(MediaType.parse("text/plain"), Constantes.MESSAGE);
RequestBody filecomment = RequestBody.create(MediaType.parse("text/plain"), Constantes.FILECOMMENT);
RequestBody api_token = RequestBody.create(MediaType.parse("text/plain"), Constantes.api_token);
RequestBody user_id = RequestBody.create(MediaType.parse("text/plain"), Integer.toString(Constantes.id));

2. Retrofit/OkHttpClient实例生命周期问题

如果你的BeeMappingClient是局部变量(比如在某个方法内临时创建),方法执行完毕后对象会被GC回收,导致Retrofit的请求被取消,自然不会触发回调。

修正方式:把BeeMappingClient改成全局单例,或者作为Activity/Fragment的成员变量,确保在请求完成前不会被销毁。

3. 缺少网络权限(Android平台)

如果是Android项目,别忘了在AndroidManifest.xml中添加网络权限,否则请求根本发不出去:

<uses-permission android:name="android.permission.INTERNET"/>

4. 添加日志拦截器排查请求细节

建议给OkHttpClient添加日志拦截器,这样能在Logcat里看到完整的请求发送、服务器响应细节,判断请求是否真的发出去了:

首先添加依赖(Gradle):

implementation 'com.squareup.okhttp3:logging-interceptor:4.11.0'

然后修改Retrofit创建代码:

OkHttpClient client = new OkHttpClient.Builder()
    .connectTimeout(30, TimeUnit.SECONDS) // 添加超时时间,避免无限等待
    .readTimeout(30, TimeUnit.SECONDS)
    .writeTimeout(30, TimeUnit.SECONDS)
    .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
    .build();

retrofit= new Retrofit.Builder()
    .baseUrl(url)
    .client(client) // 关联自定义OkHttpClient
    .addConverterFactory(ScalarsConverterFactory.create())
    .addConverterFactory(GsonConverterFactory.create())
    .build();

添加超时时间后,如果请求超时会触发onFailure,方便你排查问题。

二、当前上传方式的优化建议

你的Multipart上传方式是标准实现,但可以做几个优化让代码更简洁、高效:

1. 使用@PartMap简化参数传递

不用一个个写@Part,把所有非文件参数放到Map里,代码更简洁:

// 修改接口定义
@Multipart
@POST("task")
Call<ResponsetTask> API_Task(@Header("Authorization") String key, 
                            @Part MultipartBody.Part multipartImage, 
                            @PartMap Map<String, RequestBody> params);

// 请求调用时构建参数Map

Map<String, RequestBody> params = new HashMap<>();
params.put("message", RequestBody.create(MediaType.parse("text/plain"), Constantes.MESSAGE));
params.put("filecomment", RequestBody.create(MediaType.parse("text/plain"), Constantes.FILECOMMENT));
params.put("api_token", RequestBody.create(MediaType.parse("text/plain"), Constantes.api_token));
params.put("user_id", RequestBody.create(MediaType.parse("text/plain"), Integer.toString(Constantes.id)));

Call<ResponsetTask> call = conexion.API_Task(Constantes.AUTH, multipartImageList[0], params);

2. 单例化Retrofit和OkHttpClient

避免每次请求都创建新的Retrofit/OkHttpClient实例,节省资源,同时统一配置(比如拦截器、超时时间)。

3. 处理回调中的异常

现在你的onFailure是空实现,建议添加日志打印,方便排查问题:

@Override
public void onFailure(Call<ResponsetTask> call, Throwable t) {
    Log.e("RetrofitError", "请求失败: " + t.getMessage());
    t.printStackTrace();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:08:56