Android/iOS端通过Retrofit发送Base64位图至服务器的解码异常问题
解决Retrofit发送Base64编码图片时请求体出现异常字符的问题
问题现象
Android端使用Retrofit发起POST请求,将Bitmap通过Base64编码后作为JSON请求体发送至Spring/Flask后端,偶尔出现请求体被插入异常字符的情况,导致后端解码失败;iOS端也存在相同问题,涉及图片大小约1MB,且已正确设置Content-Type: application/json; UTF-8。
核心原因分析
- Base64编码模式问题:Android中
Base64.DEFAULT会自动为超长字符串添加换行符(\n),这些换行符在JSON序列化或HTTP传输过程中可能被转义为非预期字符 - 大体积字符串传输风险:1MB图片转Base64后体积约1.3MB,超长字符串在传输时易出现编码不一致或隐性转义问题
- 序列化器隐性编码问题:部分JSON序列化器对超长字符串的UTF-8编码处理存在疏漏
解决方案
1. 修正Base64编码模式
替换Base64.DEFAULT为Base64.NO_WRAP,避免自动生成换行符:
public static String toBase64(Bitmap bitmap) { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream); // 使用NO_WRAP模式禁止添加换行符 return Base64.encodeToString(outputStream.toByteArray(), Base64.NO_WRAP); }
2. 强制Retrofit使用UTF-8编码
通过OkHttp拦截器明确设置请求编码,同时配置Gson序列化器确保编码一致性:
// 配置Gson序列化器 Gson gson = new GsonBuilder() .create(); // 构建Retrofit实例 Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create(gson)) .client(new OkHttpClient.Builder() .addInterceptor(chain -> { Request original = chain.request(); // 强制设置UTF-8编码 Request modifiedRequest = original.newBuilder() .header("Content-Type", "application/json; charset=utf-8") .build(); return chain.proceed(modifiedRequest); }) .build()) .build();
3. 优化图片体积
适当降低图片压缩质量,减少Base64字符串长度,降低传输出错概率:
// 将压缩质量从100调整为80(可根据需求调整) bitmap.compress(Bitmap.CompressFormat.JPEG, 80, outputStream);
4. 后端添加Base64预处理
在后端对接收的Base64字符串做清理,移除可能的异常字符后再解码:
- Spring示例:
import java.util.Base64; public byte[] decodeBase64(String base64Str) { // 移除所有空白字符(换行、空格等) String cleanStr = base64Str.replaceAll("\\s+", ""); return Base64.getDecoder().decode(cleanStr); }
- Flask示例:
import base64 def decode_base64(base64_str): # 移除换行符 clean_str = base64_str.replace('\n', '').replace('\r', '') return base64.b64decode(clean_str)
内容的提问来源于stack exchange,提问作者Alireza Jabbari
相关产品推荐
相关产品推荐

