Android使用Retrofit 2携带Bearer令牌上传多图片+文本到服务器问题求助
修复方案
核心问题梳理
- 上传接口未添加
@Multipart注解,Retrofit无法识别多文件上传请求格式 - Bearer令牌拼接不符合规范,缺少
Bearer前缀 - 图片参数未封装为
MultipartBody.Part类型,服务器无法识别为上传的文件资源 - 未做空文件校验,路径无效时会直接触发崩溃
1. 修改接口类代码
// 新增@Multipart注解 @Multipart @POST("invoices") Call<ResponseBody> upload( @Header("Authorization") String authorization, // 图片参数改为MultipartBody.Part类型 @Part MultipartBody.Part image1, @Part MultipartBody.Part image2, @Part MultipartBody.Part image3, @Part("invoice") RequestBody invoice );
2. 修改上传逻辑代码
UserSharedPref sharedPref = new UserSharedPref(CompletedServiceActivity.this); // 拼接Bearer令牌前缀,注意Bearer后面有一个空格 String token = "Bearer " + sharedPref.getUserToken(); // 封装图片为MultipartBody.Part,注意判断文件是否存在 MultipartBody.Part image1 = null; if (patch_img1 != null && !patch_img1.isEmpty()) { File file1 = new File(patch_img1); if (file1.exists()) { RequestBody requestFile1 = RequestBody.create(MediaType.parse("image/*"), file1); // 第一个参数对应接口的字段名,第二个是文件名,第三个是文件RequestBody image1 = MultipartBody.Part.createFormData("image1", file1.getName(), requestFile1); } } // 同上封装image2、image3 MultipartBody.Part image2 = null; if (patch_img2 != null && !patch_img2.isEmpty()) { File file2 = new File(patch_img2); if (file2.exists()) { RequestBody requestFile2 = RequestBody.create(MediaType.parse("image/*"), file2); image2 = MultipartBody.Part.createFormData("image2", file2.getName(), requestFile2); } } MultipartBody.Part image3 = null; if (patch_img3 != null && !patch_img3.isEmpty()) { File file3 = new File(patch_img3); if (file3.exists()) { RequestBody requestFile3 = RequestBody.create(MediaType.parse("image/*"), file3); image3 = MultipartBody.Part.createFormData("image3", file3.getName(), requestFile3); } } RequestBody invoice = RequestBody.create(MediaType.parse("text/plain"), invoices); WebServicesAPI request = APIClient.getApiClient("https://text.com/api/").create(WebServicesAPI.class); Call<ResponseBody> call = request.upload(token, image1, image2, image3, invoice); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { // 这里可以打印response.code()和response.errorBody(),排查服务端返回的错误信息 if (response.isSuccessful()) { // 上传成功逻辑 } else { // 服务端返回错误,打印错误内容排查问题 try { Log.e("UploadError", response.errorBody().string()); } catch (IOException e) { e.printStackTrace(); } } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { // 网络错误、本地错误排查,打印堆栈 t.printStackTrace(); } });
3. 可选优化(APIClient类增加超时配置)
当前的APIClient没有配置超时时间,上传大文件容易触发超时,可修改如下:
public class APIClient { public static Retrofit retrofit = null; public static Retrofit getApiClient(String url) { if (retrofit == null) { // 配置OkHttpClient超时时间 OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(60, TimeUnit.SECONDS) .writeTimeout(60, TimeUnit.SECONDS) .build(); Gson gson = new GsonBuilder() .setLenient() .create(); retrofit = new Retrofit.Builder() .baseUrl(url) .client(client) // 注入自定义的OkHttpClient .addConverterFactory(GsonConverterFactory.create(gson)) .build(); } return retrofit; } }
内容的提问来源于stack exchange,提问作者Sara
相关产品推荐
相关产品推荐

