在Android开发中上传图片(头像)到服务器,要先压缩图片,获取原图的长宽,然后取得压缩比例,compress到指定的质量,输出保存,然后网络上传这张图片就行了。之前分享了web前端压缩图片的方式:
web前端之HTML5压缩图片compress image with canvas
1,乾言
如果图片太大,上传不仅耗时,而且体验不好。即使加了loading效果,那还是挺耗流量的。so,果断要压缩图片再上传,android客户端,尤其要注意。
2,图片上传
压缩原图后保存在sdcard临时目录,如果压缩后的图片存在,就上传压缩的图片,没有压缩成功(不存在),就直接上原图吧。
// 压缩图片并上传
private void uploadFileInThreadByOkHttp(final Activity context, final String actionUrl, final File tempPic) {
final String pic_path = tempPic.getPath();
String targetPath = FileUtils.getThumbDir()+"compressPic.jpg";
//调用压缩图片的方法,返回压缩后的图片path
final String compressImage = PictureUtil.compressImage(pic_path, targetPath, 30);
final File compressedPic = new File(compressImage);
if (compressedPic.exists()) {
LogUtils.debug(TAG,"图片压缩上传");
uploadFileByOkHTTP(context, actionUrl, compressedPic);
}else{//直接上传
uploadFileByOkHTTP(context, actionUrl, tempPic);
}
}
3,压缩图片的关键代码
public static String compressImage(String filePath, String targetPath, int quality) {
Bitmap bm = getSmallBitmap(filePath);//获取一定尺寸的图片
int degree = readPictureDegree(filePath);//获取相片拍摄角度
if(degree!=0){//旋转照片角度,防止头像横着显示
bm=rotateBitmap(bm,degree);
}
File outputFile=new File(targetPath);
try {
if (!outputFile.exists()) {
outputFile.getParentFile().mkdirs();
//outputFile.createNewFile();
}else{
outputFile.delete();
}
FileOutputStream out = new FileOutputStream(outputFile);
bm.compress(Bitmap.CompressFormat.JPEG, quality, out);
}catch (Exception e){}
return outputFile.getPath();
}
/**
* 根据路径获得图片信息并按比例压缩,返回bitmap
*/
public static Bitmap getSmallBitmap(String filePath) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;//只解析图片边沿,获取宽高
BitmapFactory.decodeFile(filePath, options);
// 计算缩放比
options.inSampleSize = calculateInSampleSize(options, 480, 800);
// 完整解析图片返回bitmap
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(filePath, options);
}
/**
* 获取照片角度
* @param path
* @return
*/
public static int readPictureDegree(String path) {
int degree = 0;
try {
ExifInterface exifInterface = new ExifInterface(path);
int orientation = exifInterface.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
degree = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
degree = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
degree = 270;
break;
}
} catch (IOException e) {
e.printStackTrace();
}
return degree;
}
/**
* 旋转照片
* @param bitmap
* @param degress
* @return
*/
public static Bitmap rotateBitmap(Bitmap bitmap,int degress) {
if (bitmap != null) {
Matrix m = new Matrix();
m.postRotate(degress);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), m, true);
return bitmap;
}
return bitmap;
}
public static int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
4,上传图片
使用okhttp,如果不太熟悉okhttp的话,可以看我的另一博文:
Android网络请求:OkHttp实战
本文上传头像,封装uploadFile方法如下:
/**
* 上传文件
* @param url 接口地址
* @param file 上传的文件
* @param mediaType 资源mediaType类型:比如 MediaType.parse("image/png");
* @param responseCallback 回调方法,在子线程,更新UI要post到主线程
* @return
*/
public boolean uploadFile(String url, File file, MediaType mediaType, Callback responseCallback) {
MultipartBody.Builder builder = new MultipartBody.Builder().setType(MediaType.parse("multipart/form-data"));
if (!file.exists()|| TextUtils.isEmpty(url)){
return false;
}
//addFormDataPart视项目自身的情况而定
//builder.addFormDataPart("description","2.jpg");
builder.addFormDataPart("file", file.getName(), RequestBody.create(mediaType, file));
//构建请求体
RequestBody requestBody = builder.build();
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
enqueue(request,responseCallback);
return true;
}
其中的RequestBody大概是这样的:
MultipartBody.Builder builder = new MultipartBody.Builder().setType(MediaType.parse("multipart/form-data")); builder.addFormDataPart("description","duqian.jpg");
builder.addFormDataPart("file", "Dusan.jpg", RequestBody.create(MEDIA_TYPE_PNG, new File(photoPath)));
5,over,休息
哈哈,简单,如果遇到上传文件的格式限制,和后台协调下。亲测,图片压缩效果明显,不影响清晰度。你也可以自己改质量,宽高,确定压缩后的图片,网络框架嘛,很多,看个人习惯咯。
欢迎交流,Dusan,291902259,OpenDeveloper。
需要android顶尖学习资料和VIP视频的可以加我Q:291902259。