将InputStream解码为Bitmap后,Retrofit POST请求返回400错误排查
问题原因分析
核心问题是InputStream的读取指针是单向移动的,且无法重复读取:
- 你先将
inputStream传给RequestBodyUtil.create(),Retrofit会在请求发送时读取这个流的内容;但紧接着调用BitmapFactory.decodeStream(inputStream),已经把流的读取指针移动到了末尾。 - 当Retrofit真正发送请求时,尝试读取这个流已经没有数据,相当于上传了空文件,服务器接收到不完整的请求数据,因此返回400错误(请求参数无效)。
解决方案
有两种常见修复方式:
方式1:重新打开InputStream
解码Bitmap时,重新打开一个独立的InputStream,不要复用同一个流:
InputStream inputStream = null; try { inputStream = getContentResolver().openInputStream(imgUri); } catch (FileNotFoundException e) { e.printStackTrace(); } RequestBody requestBody = RequestBodyUtil.create(MediaType.get("image/" + imgType), inputStream); RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM) .addFormDataPart("messaging_product", "help") .addFormDataPart("file", "image/" + imgType, requestBody) .addFormDataPart("type", "image/" + imgType) .build(); // 解码Bitmap时重新打开新的流 InputStream bitmapInputStream = null; try { bitmapInputStream = getContentResolver().openInputStream(imgUri); Bitmap bitmap = BitmapFactory.decodeStream(bitmapInputStream); Log.d(TAG, "onClick: "); } catch (FileNotFoundException e) { e.printStackTrace(); } finally { if (bitmapInputStream != null) { try { bitmapInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } // 后续请求代码不变 Call<ModelGraphResponse> call = RetrofitInstance.getRetrofitClient().create(IService.class).uploadImageToGraph(name, body);
方式2:将流内容缓存到内存(适合小图片)
把InputStream的内容读取到字节数组,再分别用于RequestBody和Bitmap解码:
byte[] imageBytes = null; InputStream inputStream = null; try { inputStream = getContentResolver().openInputStream(imgUri); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len; while ((len = inputStream.read(buffer)) != -1) { baos.write(buffer, 0, len); } imageBytes = baos.toByteArray(); } catch (IOException e) { e.printStackTrace(); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } // 用字节数组创建RequestBody RequestBody requestBody = RequestBodyUtil.create(MediaType.get("image/" + imgType), imageBytes); RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM) .addFormDataPart("messaging_product", "help") .addFormDataPart("file", "image/" + imgType, requestBody) .addFormDataPart("type", "image/" + imgType) .build(); // 用字节数组解码Bitmap Bitmap bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); Log.d(TAG, "onClick: "); // 后续请求代码不变 Call<ModelGraphResponse> call = RetrofitInstance.getRetrofitClient().create(IService.class).uploadImageToGraph(name, body);
注意:如果图片体积较大,方式2可能引发内存溢出,此时优先选择方式1。
内容的提问来源于stack exchange,提问作者Prasath S
相关产品推荐
相关产品推荐

