Retrofit提供了更方便的上传(表单): Retrofit2 使用@Multipart上传文件
但是,有些特殊的需求,服务端以json格式接收图片信息,Android端需要将图片转换成base64,上传到服务端。
1、图片需要转换成base64:
1、使用 android.util.Base64;
2、编码格式设置为:NO_WRAP(消除换行符);
- DEFAULT 这个参数是默认,使用默认的方法来加密
- CRLF 这个参数看起来比较眼熟,它就是Win风格的换行符,意思就是使用CRLF 这一对作为一行的结尾而不是Unix风格的LF
- NO_PADDING 这个参数是略去加密字符串最后的”=”
- NO_WRAP 这个参数意思是略去所有的换行符(设置后CRLF就没用了)
- URL_SAFE 这个参数意思是加密时不使用对URL和文件名有特殊意义的字符来作为加密字符,具体就是以-和 _ 取代+和/
/**
* 将图片转换成Base64编码的字符串
* <p>
* https://blog.csdn.net/qq_35372900/article/details/69950867
*/
public static String imageToBase64(File path) {
InputStream is = null;
byte[] data;
String result = null;
try {
is = new FileInputStream(path);
//创建一个字符流大小的数组。
data = new byte[is.available()];
//写入数组
is.read(data);
//用默认的编码格式进行编码
result = Base64.encodeToString(data, Base64.NO_WRAP);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != is) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
2、接口声明:
注意,以Json格式请求:
addHeader(“Content-Type”, “application/json”);
//实体类形式
@POST(pathUrl + "/vehicle/gather")
Call<HttpBaseResult<VehicleResponse>> uploadInfo2(@Body UploadInfo uploadInfo);
//Map形式
@POST(pathUrl + "/vehicle/gather")
Call<HttpBaseResult<VehicleResponse>> uploadInfo3(@Body Map<String, String> files);
//表单形式上传
@POST("kits-jcz-server/app/pv/id/save")
@Multipart
fun savePersonInfoByID(@PartMap body: MutableMap<String, RequestBody>): Call<HttpBaseResult<Any>>
3、接口调用
3.1、接口调用1(Map形式):
public static Map<String, String> getRequestMap(Context mContext, VehicleResponse response) {
Map<String, String> map = new HashMap<>();
String imageUrl = response.getImgUrl();
File file = null;
try {
file = Luban.with(mContext).load(imageUrl).get(imageUrl);
} catch (IOException e) {
e.printStackTrace();
}
String imgBase64 = imageToBase64(file);
map.put("file", imgBase64);
map.put("plateNo", response.getPlateNo());
...
map.put("gatherTime", DateUtil.Long2String(response.getGatherTime(), "yyyy-MM-dd HH:mm:ss"));
map.put("userCode", VehicleCollectSp.getUserName());
return map;
}
private void uploadInfo(VehicleResponse response) {
serviceApi.uploadInfo3(BizUtil.getRequestMap(mContext, response)).enqueue(new HttpRequestCallback<VehicleResponse>() {
@Override
public void onSuccess(VehicleResponse result) {
super.onSuccess(result);
LegoLog.d("上传成功,result:" + result.getImgUrl());
});
}
@Override
public void onFailure(int status, String message) {
super.onFailure(status, message);
LegoLog.d("上传失败,message:" + message);
}
});
}
}
3.2、接口调用2(实体类形式):
private void uploadInfo(VehicleResponse response) {
serviceApi.uploadInfo2(BizUtil.getUploadInfo(mContext, response)).enqueue(new HttpRequestCallback<VehicleResponse>() {
@Override
public void onSuccess(VehicleResponse result) {
super.onSuccess(result);
LegoLog.d("上传成功,result:" + result.getImgUrl());
});
}
@Override
public void onFailure(int status, String message) {
super.onFailure(status, message);
LegoLog.d("上传失败,message:" + message);
}
});
}
public static UploadInfo getUploadInfo(Context mContext, VehicleResponse response) {
UploadInfo info = new UploadInfo();
String imageUrl = response.getImgUrl();
File file = null;
try {
file = Luban.with(mContext).load(imageUrl).get(imageUrl);
} catch (IOException e) {
e.printStackTrace();
}
String imgBase64 = imageToBase64(file);
info.setFile(imgBase64);
info.setPlateNo(response.getPlateNo());
...
return info;
}
3.3、表单上传
private fun getRequestMap(id: Int): MutableMap<String, RequestBody> {
val map: MutableMap<String, RequestBody> = mutableMapOf()
val base64 = "data:image/png;base64,i"
map["carRecordId"] = toRequestBody(id.toString())
map["name"] = toRequestBody("caowj$id")
map["idNum"] = toRequestBody("320321167567876546")
map["idImageData"] = toRequestBody(base64)
map["dpsType"] = toRequestBody("dpsType")
map["dpsLevel"] = toRequestBody("dpsLevel")
map["matchedResult"] = toRequestBody("1")
map["sim"] = toRequestBody("86%")
map["faceImageData"] = toRequestBody(base64)
return map
}
fun addPerson(id: Int) {
HttpServicesFactory.getCheckpointApi().savePersonInfoByID(getRequestMap(id)).enqueue(object : HttpCallback<Any>() {
override fun onSuccess(result: Any?) {
showToast("添加人员成功")
LegoEventBus.use(CheckpointConstant.EVENT_KEY_REFRESH_DETAIL_DATA).postValue(true)
}
})
}
postman示例: