在Android开发过程中,肯定会遇到与后端进行交互的地方。手机端与后端进行交互,难免会使用到OkGo。在最近的一个项目中,明明是按照官方教程写的代码,但是始终会报一个异常。
报错信息:
network error! http response code is 404 or 5xx
开始以为是服务端接口的问题,但是使用Apipost接口测试工具测试了一下接口,可以正常调用。这就说明是手机端出了问题。
先说一下,使用OkGo上传文件的用法;
//上传单个文件
//url:服务器地址
//filesDir:手机图片的文件夹
//fileName:图片名
String url = Constants.USER_NET_ICON;
File file = new File(filesDir, fileName);
OkGo.<String>post(url)
.tag(this)
.params("discript","miaoshuxinxi")
.params("icon", file)
.isMultipart(true)
.execute(new StringCallback() {
@Override
public void onSuccess(Response<String> response) {
LogUtil.e("上传成功" + response.body());
}
@Override
public void onError(Response<String> response) {
LogUtil.e("上传失败" + response.body());
}
});
开始我的写的是这种写法,进行上传的。结果就是报了上面的异常信息。重新检查接口路径均未找到问题所在。就在一筹莫展时,想起可能是安卓版本问题造成,果然在使用安卓7版本时,尽然走通了。就想到了一个问题。
在官方7.0的以上的系统中,尝试传递 file://URI可能会触发FileUriExposedException。
之后就使用FileProvider,将手机存储卡中的图片路径转换成url,加载到OkGo中,发现依旧不对。后来想到将将这个url转化成Bitmap。然后再将bitmap转成File。思路整理出来了,就进入实践,代码如下:
将url转成bitmap,然后再转成file
/**
*将bitmap转为File
*上传图片时,需要将bitmap转换成File,不能直接用File上传
* url为图片的路径,name为照片的文件名
*/
public File getFile(Uri uri, String name) {
Bitmap bitmap = null;
try {
bitmap = BitmapFactory.decodeStream(this.getContentResolver().openInputStream(uri));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, baos);
File file = new File(PICTURE_FILE_DIR + name);
try {
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
InputStream is = new ByteArrayInputStream(baos.toByteArray());
int x = 0;
byte[] b = new byte[1024 * 100];
while ((x = is.read(b)) != -1) {
fos.write(b, 0, x);
}
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
return file;
}
之后再在OkGo中调用getFile()方法。
String url = Constants.USER_NET_ICON;
OkGo.<String>post(url)
.tag(this)
.params("discript","miaoshuxinxi")
.params("icon", getFile(uri,fileName))
.isMultipart(true)
.execute(new StringCallback() {
@Override
public void onSuccess(Response<String> response) {
LogUtil.e("上传成功" + response.body());
}
@Override
public void onError(Response<String> response) {
LogUtil.e("上传失败" + response.body());
}
});
发现终于上传成功了。特此记录一下,也给其他又遇到类似问题的开发者一些启发。
至于如何将手机存储卡中的图片转成url,可以百度一下FileProvider的用法。