使用Retrofit 2.1.0发送Multipart图片时出现Bad Request错误
解决Retrofit 2.1.0 Multipart上传图片的Bad Request问题
看起来你在使用Retrofit 2.1.0以Multipart形式上传图片时遇到了Bad Request错误,我来帮你排查可能的问题并给出修复方案:
可能的问题点及修复步骤
1. 媒体类型(MediaType)不够明确
你当前使用的是MediaType.parse("image/*"),部分服务器可能不接受通配符类型,需要指定具体的图片格式(比如JPEG、PNG)。建议根据文件的后缀名来设置对应的MediaType:
// 获取文件后缀名,判断图片类型 String extension = MimeTypeMap.getFileExtensionFromUrl(savedpath); String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); if (mimeType == null) { // 默认设置为jpeg mimeType = "image/jpeg"; } RequestBody requestFile = RequestBody.create(MediaType.parse(mimeType), file);
2. 检查文件是否存在及权限
Bad Request也可能是因为文件不存在或者应用没有读取文件的权限。在创建File对象后,先添加检查:
File file = new File(savedpath); if (!file.exists() || !file.isFile()) { Toast.makeText(DetailActiveSRActivity.this, "文件不存在或无效", Toast.LENGTH_SHORT).show(); hideLoader(); return; } // 另外,确保你已经申请了读取外部存储的权限(Android 6.0及以上需要动态申请)
3. 核对接口参数与服务器要求
- 确认服务器端接收图片的参数名是否是
"image",你的代码里用的是createFormData("image", file.getName(), requestFile),如果服务器要求的参数名不同(比如"file"),就会导致错误。 - 检查
userId的参数名是否正确,你的接口里是@Part("userId") RequestBody userId,确保服务器端接收的参数名一致。 - 检查Header中的
authkey是否正确,你设置的是ABCD@123,确认这个值和服务器要求的匹配。
4. 额外排查技巧
在onResponse中打印服务器返回的错误详情,能帮你快速定位问题:
if (!response.isSuccessful()) { Log.e(TAG, "onResponse: Error code " + response.code() + ", message: " + response.message()); try { Log.e(TAG, "Error body: " + response.errorBody().string()); } catch (IOException e) { e.printStackTrace(); } Toast.makeText(DetailActiveSRActivity.this, "请求失败:" + response.message(), Toast.LENGTH_SHORT).show(); return; }
修改后的完整代码示例
private void saveImageToServer(final String savedpath) { showLoader(); NetworkUtil.checkInternetConnection(DetailActiveSRActivity.this, new NetworkUtil.NetworkStatusListener() { @Override public void onNetworkAvailable() { File file = new File(savedpath); // 检查文件有效性 if (!file.exists() || !file.isFile()) { Toast.makeText(DetailActiveSRActivity.this, "文件不存在或无效", Toast.LENGTH_SHORT).show(); hideLoader(); return; } // 获取正确的媒体类型 String extension = MimeTypeMap.getFileExtensionFromUrl(savedpath); String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); if (mimeType == null) { mimeType = "image/jpeg"; } RequestBody requestFile = RequestBody.create(MediaType.parse(mimeType), file); Log.e(TAG, "onNetworkAvailable: requestFIle " + savedpath+"\n"+" file "+file); MultipartBody.Part body = MultipartBody.Part.createFormData("image", file.getName(), requestFile); Log.e(TAG, "onNetworkAvailable: body " + body); RequestBody reqUserId = RequestBody.create(MediaType.parse("text/plain"), userId); //RequestBody reqImageType =RequestBody.create(MediaType.parse("text/plain"), "1"); Call<SaveImageResponseModel> responseCall = mService.saveImages(body, reqUserId); responseCall.enqueue(new Callback<SaveImageResponseModel>() { @Override public void onResponse(Call<SaveImageResponseModel> call, retrofit2.Response<SaveImageResponseModel> response) { hideLoader(); // 打印错误详情 if (!response.isSuccessful()) { Log.e(TAG, "onResponse: Error code " + response.code() + ", message: " + response.message()); try { Log.e(TAG, "Error body: " + response.errorBody().string()); } catch (IOException e) { e.printStackTrace(); } Toast.makeText(DetailActiveSRActivity.this, "请求失败:" + response.message(), Toast.LENGTH_SHORT).show(); return; } if (response != null) { SaveImageResponseModel apiResponse = response.body(); if (apiResponse != null && apiResponse.getStatus()) { Log.e(TAG, "onRequestSuccess: " + apiResponse); } else { Toast.makeText(DetailActiveSRActivity.this, getString(R.string.noDataError), Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(DetailActiveSRActivity.this, getString(R.string.noDataError), Toast.LENGTH_SHORT).show(); } } @Override public void onFailure(Call<SaveImageResponseModel> call, Throwable t) { hideLoader(); Log.e(TAG, "onFailure: ", t); Toast.makeText(DetailActiveSRActivity.this, "请求失败:" + t.getMessage(), Toast.LENGTH_SHORT).show(); } }); } @Override public void onNetworkNotAvailable() { Toast.makeText(DetailActiveSRActivity.this, getString(R.string.noNetworkMessage), Toast.LENGTH_SHORT).show(); hideLoader(); } }); } // 接口部分保持不变,确认参数名与服务器匹配即可 @Headers({ "authkey: ABCD@123" }) @Multipart @POST(UrlUtils.POST_IMAGES) Call<SaveImageResponseModel> saveImages(@Part MultipartBody.Part file, @Part("userId") RequestBody userId);
内容的提问来源于stack exchange,提问作者Krishna mohan
相关产品推荐
相关产品推荐

