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
相关产品推荐
相关产品推荐

