Android学习-使用Async-Http实现图片压缩并上传功能
前言
(转载请注明出处,谢谢!)
最近在做一个小项目,项目中要实现上传图片到服务器,而这个例子是实现图片的尺寸压缩,将获取到的压缩图片转为流,然后使用Async-Http开源框架实现图片流的上传,然后在服务器端将流写入本地。
效果图
<center>
<center>安卓端</center>
<center>
<center>服务器端</center>
解决
安卓端
一、点击加载本地相册选择图片,然后加载到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);
}
});//在选择图片后返回本界面调用此方法@Overrideprotected 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);
}
}
点击查看更多内容
1人点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦