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

Android端调用Update Profile API返回200但数据未写入数据库

Android更新个人资料接口返回200但数据库未写入问题

问题详情

Android应用调用form-data类型的POST接口更新个人资料,接口返回状态码200且提示"更新成功",但数据库中数据未被修改。使用Postman调用同一接口可正常写入数据库,且应用代码未做任何修改,此问题为突然出现。

相关代码

API处理类

import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class ApiHandler {

    private static final String BASE_URL = "https://rndtd.com/demos/scrapbazar/api/";

    private static Retrofit retrofit;

    public static Retrofit getRetrofitInstance() {

        if(retrofit == null){
          
            retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }

        return retrofit;
    }
}

API接口定义

public interface ApiInterface {

    @GET("allProducts")
    Call<List<List<Product>>> getAllProducts();

    @Multipart
    @POST("updateprofile")
    Call<ResponseBody> updateUserProfile(
            @Part("id") int id,
            @Part("first_name") String userName,
            @Part("email") String email,
            @Part MultipartBody.Part image
            );
}

API调用方法

public void updateProfile() {

    ApiInterface apiInterface = getRetrofitInstance().create(ApiInterface.class);

    int id = SaveSharedPreference.getUserId(this);
    String userName = etUserName.getText().toString();
    String email = etEmail.getText().toString();

    if (userName.isEmpty() || email.isEmpty() || selectedImageUri == null) {
        mProgress.dismiss();
        Toast.makeText(this, "All fields are required", Toast.LENGTH_SHORT).show();
        return; // Exit the method if any field is missing
    }

    if (selectedImageUri != null) {
        String fileName = getFileName(selectedImageUri);
       
        File imageFile = new File(getCacheDir(), fileName);

        try {
            InputStream inputStream = getContentResolver().openInputStream(selectedImageUri);
            FileOutputStream fileOutputStream = new FileOutputStream(imageFile);
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                fileOutputStream.write(buffer, 0, bytesRead);
            }
            inputStream.close();
            fileOutputStream.close();

        }
        catch (IOException e)  {
            e.printStackTrace();
        }

        RequestBody imageRequestFile = RequestBody.create(MediaType.parse(getMimeType(selectedImageUri)), imageFile);
        MultipartBody.Part imagePart = MultipartBody.Part.createFormData("image", imageFile.getName(), imageRequestFile);

        Log.d("Request Data", "ID: " + id);
        Log.d("Request Data", "UserName: " + userName);
        Log.d("Request Data", "Email: " + email);
        Log.d("Request Data", "image: " + imagePart);

        Call<ResponseBody> call = apiInterface.updateUserProfile(id, userName, email, imagePart);

        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {

                int responseCode = response.code();
                Toast.makeText(EditProfile.this, "code : " + responseCode, Toast.LENGTH_SHORT).show();

                if (response.isSuccessful()) {

                    String msg = "Customer Updated Successfully";
                    Toast.makeText(EditProfile.this, "" + msg, Toast.LENGTH_SHORT).show();
                    finish();

                } else {
                    mProgress.dismiss();
                    Toast.makeText(EditProfile.this, "Response is not success", Toast.LENGTH_SHORT).show();
                }

            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                mProgress.dismiss();
                Log.e("Tag", "Error : " + t.getLocalizedMessage());
                Toast.makeText(EditProfile.this, "Error " + t.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
            }
        });
    }
} 

Logcat日志

ID: 2
UserName: myName
Email: myName@gmail.com
image: okhttp3.MultipartBody$Part@2afca0d

排查与解决方案

1. 修正非文件参数的注解方式

Retrofit中@Multipart接口的非文件参数,直接传递基本类型/字符串可能导致参数格式不符合form-data要求,需改用RequestBody包裹:
修改API接口定义:

@Multipart
@POST("updateprofile")
Call<ResponseBody> updateUserProfile(
        @Part("id") RequestBody id,
        @Part("first_name") RequestBody userName,
        @Part("email") RequestBody email,
        @Part MultipartBody.Part image
        );

调用时转换参数:

RequestBody idBody = RequestBody.create(MediaType.parse("multipart/form-data"), String.valueOf(id));
RequestBody userNameBody = RequestBody.create(MediaType.parse("multipart/form-data"), userName);
RequestBody emailBody = RequestBody.create(MediaType.parse("multipart/form-data"), email);

Call<ResponseBody> call = apiInterface.updateUserProfile(idBody, userNameBody, emailBody, imagePart);

2. 添加OkHttpClient日志拦截器,对比请求差异

添加日志拦截器查看实际发送的请求内容,和Postman的请求做对比:
修改ApiHandler类,配置带日志拦截器的OkHttpClient:

import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class ApiHandler {

    private static final String BASE_URL = "https://rndtd.com/demos/scrapbazar/api/";

    private static Retrofit retrofit;

    public static Retrofit getRetrofitInstance() {

        if(retrofit == null){
            // 添加日志拦截器
            HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
            logging.setLevel(HttpLoggingInterceptor.Level.BODY);
            
            OkHttpClient client = new OkHttpClient.Builder()
                    .addInterceptor(logging)
                    .build();
          
            retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .client(client)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }

        return retrofit;
    }
}

通过Logcat查看完整请求体,对比Postman的请求头、参数名、参数值是否一致。

3. 检查缓存文件是否有效

确认缓存目录中的imageFile是否正确写入了图片内容,可添加文件大小日志:

Log.d("File Info", "Image file size: " + imageFile.length());

如果文件大小为0,说明图片复制过程出错,需检查getContentResolver().openInputStream(selectedImageUri)是否获取到有效流。

4. 验证后端接口的参数校验逻辑

虽然Postman调用正常,但可能后端对请求头、参数格式有隐性要求(比如Accept头),可在OkHttpClient中添加统一请求头:

OkHttpClient client = new OkHttpClient.Builder()
        .addInterceptor(logging)
        .addInterceptor(chain -> {
            Request original = chain.request();
            Request request = original.newBuilder()
                    .header("Accept", "application/json")
                    .build();
            return chain.proceed(request);
        })
        .build();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 06:41:30