文档章节

Android学习-使用Async-Http实现图片压缩并上传功能

Ryane
 Ryane
发布于 2016/06/14 13:09
字数 1267
阅读 356
收藏 3

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);
		}
	}

 

Demo地址

 

http://download.csdn.net/detail/ljcitworld/9548619

© 著作权归作者所有

Ryane
粉丝 42
博文 22
码字总数 55318
作品 0
程序员
私信 提问
六款值得推荐的android(安卓)开源框架简介【转】

1、volley 项目地址 https://github.com/smanikandan14/Volley-demo (1) JSON,图像等的异步下载; (2) 网络请求的排序(scheduling) (3) 网络请求的优先级处理 (4) 缓存 (5) 多级别取消请求...

hkstar35
2014/07/11
290
0
六款值得推荐的android(安卓)开源框架简介【转】

1、volley 项目地址 https://github.com/smanikandan14/Volley-demo (1) JSON,图像等的异步下载; (2) 网络请求的排序(scheduling) (3) 网络请求的优先级处理 (4) 缓存 (5) 多级别取消请求...

火蚁
2014/07/09
668
1
Android学习-手把手教学实现仿微信发带图片朋友圈的UI设计

最近自己在开发一个社交APP,发送动态(类似朋友圈)是社交APP必备的一个功能,而自己在开发过程中也需要开发到这一个功能,但是在开发中遇到了一个问题,就是如何绘制一个类似朋友群那样动态...

Ryane
2016/06/14
1K
0
ReactNative IOS模块

[背景] 目前已经开发好相同功能的android版本,本人不会ios开发,无从下手 [需求] 1、语音录制模块 功能需求:语音(开始、停止、试听)、压缩后上传到指定服务器 接收标准: a、IOS端原生模...

孟凯
2016/05/22
14
0
Android应用开发之使用PhoneGap实现拍照上传功能

看这里:Android应用开发之使用PhoneGap实现拍照上传功能 在之前的使用Intellij Idea 搭建PhoneGap Android开发环境以及Android应用开发之使用PhoneGap实现位置上报功能两篇文章中,我们学习...

Realfighter
2015/02/05
10.6K
3

没有更多内容

加载失败,请刷新页面

加载更多

js如何控制table中的某一行动态置顶

两行代码搞定: $('#'+item.roadCode).fadeOut().fadeIn();//获取到需要置顶的行 $(".table").prepend($('#'+item.roadCode)); 其中,fadeOut()方法 作用 --- 从可见到隐藏 如下: prepend(......

码妞
55分钟前
3
0
四种解决Nginx出现403 forbidden 报错的方法

我是在在本地用虚拟机中通过yum安装nginx的,安装一切正常,但是访问时报403, 于是查看nginx日志,路径为/var/log/nginx/error.log。打开日志发现报错Permission denied,详细报错如下: 1....

dragon_tech
今天
3
0
获取RestResultResponse返回的值

Springboot项目,需要调其他服务的接口,返回值类型是RestResultResponse 打断点的结果集是这个 打印出来的getData(): [{id=3336b624-8474-4dd9-bd5b-c7358687c877, paraNo=104, para=Postpo...

栾小糖
今天
4
0
【小学】 生成10以内的加减法

#!/usr/bin/env python# coding: utf-8from random import randrange# 题目的最大数值R_MAX = 10# 生成的题目的数量R_PAGE = 70# 生成减法列表def get_sub_list():...

Tensor丨思悟
今天
11
0
JavaScript设计模式——适配器模式

  适配器模式是设计模式行为型模式中的一种模式;   定义:   适配器用来解决两个已有接口之间不匹配的问题,它并不需要考虑接口是如何实现,也不用考虑将来该如何修改;适配器不需要修...

有梦想的咸鱼前端
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部