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

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

前言

(转载请注明出处,谢谢!)

最近在做一个小项目,项目中要实现上传图片到服务器,而这个例子是实现图片的尺寸压缩,将获取到的压缩图片转为流,然后使用Async-Http开源框架实现图片流的上传,然后在服务器端将流写入本地。

效果图

Android学习-使用Async-Http实现图片压缩并上传功能_第1张图片
安卓端
Android学习-使用Async-Http实现图片压缩并上传功能_第2张图片
服务器端

解决

安卓端

一、点击加载本地相册选择图片,然后加载到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

你可能感兴趣的:(Android学习-使用Async-Http实现图片压缩并上传功能)