Android学习-使用Async-Http实现图片压缩并上传功
2016-06-14 本文已影响1523人
08dc70a40fb1
Android学习-使用Async-Http实现图片压缩并上传功能
前言
(转载请注明出处,谢谢!)
最近在做一个小项目,项目中要实现上传图片到服务器,而这个例子是实现图片的尺寸压缩,将获取到的压缩图片转为流,然后使用Async-Http开源框架实现图片流的上传,然后在服务器端将流写入本地。
效果图
安卓端 服务器端解决
安卓端
一、点击加载本地相册选择图片,然后加载到ImageView中去,并获取图片地址以供后面图片上传时使用。
//点击图片打开选择图片界面
photo.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//使用Intent触发选择Action
Intent intent = new Intent(Intent.ACTION_PICK, null);
//打开系统提供的图片选择界面
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
//传参以在返回本界面时触发加载图片的功能
startActivityForResult(intent, 0x1);
}
});
//在选择图片后返回本界面调用此方法
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 0x1 && resultCode == RESULT_OK) {
if (data != null) {
ContentResolver resolver = getContentResolver();
try {
// 获取圖片URI
Uri uri = data.getData();
// 将URI转换为路径:
String[] proj = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(uri, proj, null, null, null);
// 这个是获得用户选择的图片的索引值
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
// 最后根据索引值获取图片路径
photoPath = cursor.getString(column_index);
// 压缩成800*480
bitmap = BitmapUtils.decodeSampledBitmapFromFd(photoPath, 480, 800);
// 设置imageview显示图片
photo.setImageBitmap(bitmap);
// 设置textview显示路径
path.setText(photoPath);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
二、图片压缩。在我们需要上传图片时,我们不可能直接把原图上传到服务器,因为一般图片的大小都超过3,4M,所以我们在上传之前需要对图片进行压缩,我是把图片压缩放到了一个工具类,主要是对图片进行尺寸压缩。
public class BitmapUtils {
private 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 halfHeight = height / 2;
final int halfWidth = width / 2;
//循环,如果halfHeight和halfWidth同时大于最小宽度和最小高度时,inSampleSize乘2,
//最后得到的宽或者高都是最接近最小宽度或者最小高度的
while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
/**
* 根据Resources压缩图片
*
* @param res
* @param resId
* @param reqWidth
* @param reqHeight
* @return
*/
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds = false;
Bitmap src = BitmapFactory.decodeResource(res, resId, options);
return src;
}
/**
* 根据地址压缩图片
*
* @param pathName
* @param reqWidth 最小宽度
* @param reqHeight 最小高度
* @return
*/
public static Bitmap decodeSampledBitmapFromFd(String pathName, int reqWidth, int reqHeight) {
final BitmapFactory.Options options = new BitmapFactory.Options();
// 若要对图片进行压缩,必须先设置Option的inJustDecodeBounds为true才能进行Option的修改
options.inJustDecodeBounds = true;
// 第一次decodeFile是获取到options.outHeight和options.outWidth
BitmapFactory.decodeFile(pathName, options);
// options.inSampleSize是图片的压缩比,例如原来大小是100*100,options.inSampleSize为1,则不变,
// options.inSampleSize为2,则压缩成50*50
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// 重新设置options.inJustDecodeBounds为false,不能修改option
options.inJustDecodeBounds = false;
// 根据options重新加载图片
Bitmap src = BitmapFactory.decodeFile(pathName, options);
return src;
}
}
三、将Bitmap转为String,同时使用BASE64加密,使传输更加安全,这是我的工具类,里面再一次进行压缩是质量压缩,压缩比例是30%,具体自己调
public class Utils {
// 将bitmap转成string类型通过Base64
public static String BitmapToString(Bitmap bitmap) {
ByteArrayOutputStream bao = new ByteArrayOutputStream();
// 将bitmap压缩成30%
bitmap.compress(Bitmap.CompressFormat.JPEG, 30, bao);
// 将bitmap转化为一个byte数组
byte[] bs = bao.toByteArray();
// 将byte数组用BASE64加密
String photoStr = Base64.encodeToString(bs, Base64.DEFAULT);
// 返回String
return photoStr;
}
}
四、通过Async-Http实现图片上传
public void upload(String url) {
// 将bitmap转为string,并使用BASE64加密
String photo = Utils.BitmapToString(bitmap);
// 获取到图片的名字
String name = photoPath.substring(photoPath.lastIndexOf("/")).substring(1);
// new一个请求参数
RequestParams params = new RequestParams();
// 将图片和名字添加到参数中
params.put("photo", photo);
params.put("name", name);
AsyncHttpClient client = new AsyncHttpClient();
// 调用AsyncHttpClient的post方法
client.post(url, params, new AsyncHttpResponseHandler() {
@Override
public void onFailure(int arg0, Header[] arg1, byte[] arg2, Throwable arg3) {
Toast.makeText(getApplicationContext(), "上传失败!", Toast.LENGTH_SHORT).show();
}
@Override
public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {
Toast.makeText(getApplicationContext(), "上传成功!", Toast.LENGTH_SHORT).show();
}
});
}
服务器端
一、创建一个新的Servlet,在doget方法里面实现
public class UpLoadPhotoServlet extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html");
// 获取文件名
String name = request.getParameter("name");
// 获取图片
String photo = request.getParameter("photo");
// 将传进来的图片的string格式进行处理
byte[] bs = new BASE64Decoder().decodeBuffer(photo);
// 写到E盘Img文件夹下的a.jpg文件。注:Img文件夹一定要存在
FileOutputStream fos = new FileOutputStream("E:/Img/" + name);
fos.write(bs);
fos.flush();
fos.close();
PrintWriter writer = response.getWriter();
writer.print("上传成功");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}