Android图片压缩并上传到服务器

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yrmao9893/article/details/70599061

转载请说明出处 http://write.blog.csdn.net/postedit/70599061

最近公司又叫开发了一个新项目,这个项目中上传图片用的蛮多的,于是整理一下,记录自己的心得体验

刚入手的时候,对于图片的大小还没有概念,(以前上传图片都是用户头像,对大小没什么要求),心想之间上传就是了,和以前一样,那成想到,上传一张图片还好,上传多张图片慢成狗,这时候,我还是无动于衷,直到有一天,服务器端也意识到了,图片太大对数据库没好处,只会让数据库变得无比庞大,限制的上传图片的大小,单张图片最大为2w,此时的我,再也不能无动于衷了,默默的进行图片的压缩,而我对于图片的压缩可以用一无所知来形容,尽管上学的时候学习过,只好借鉴Google了,压缩图片方法大致分为如下几类,

1.质量压缩

2.采样率压缩

3.缩放法压缩

4.RGB_565

5.createScaledBitmap

参考文章:http://blog.csdn.net/harryweasley/article/details/51955467

而我采用的是质量压缩方法

废话不多说直接看看效果图(这里直接用了公司项目中的图片截的屏幕)

压缩前的图片截图:       

点击其中一张图片

上传并压缩后的截图

点击其中一张小图

在送一张好图

由肉眼辨别,貌似压缩前和压缩后的分辨率·,没有什么区别。

我也简单的做了一下对比,压缩前图片的大小为5w左右,压缩后的大小为100k左右,这似乎满足了我的需求(内心有点小激动!)

代码说明  首先说明一下,使用的网络请求库是:Retrofit2+Rxjava2  ps 还不知道这个是什么东东的童鞋,I 服了you

压缩图片的工具类BitmapUtil

/**
 * Created by yemao on 2017/3/15.
 * 关于图片的工具类
 */

public class BitmapUtil {
   
    private static String PHOTO_FILE_NAME = "PMSManagerPhoto";

    /**
     * 获取图片的旋转角度
     *
     * @param filePath
     * @return
     */
    public static int getRotateAngle(String filePath) {
        int rotate_angle = 0;
        try {
            ExifInterface exifInterface = new ExifInterface(filePath);
            int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    rotate_angle = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    rotate_angle = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    rotate_angle = 270;
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return rotate_angle;
    }

    /**
     * 旋转图片角度
     *
     * @param angle
     * @param bitmap
     * @return
     */
    public static Bitmap setRotateAngle(int angle, Bitmap bitmap) {

        if (bitmap != null) {
            Matrix m = new Matrix();
            m.postRotate(angle);
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                    bitmap.getHeight(), m, true);
            return bitmap;
        }
        return bitmap;

    }

    //转换为圆形状的bitmap
    public static Bitmap createCircleImage(Bitmap source) {
        int length = source.getWidth() < source.getHeight() ? source.getWidth() : source.getHeight();
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        Bitmap target = Bitmap.createBitmap(length, length, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(target);
        canvas.drawCircle(length / 2, length / 2, length / 2, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(source, 0, 0, paint);
        return target;
    }

  

    /**
     * 图片压缩-质量压缩
     *
     * @param filePath 源图片路径
     * @return 压缩后的路径
     */

    public static String compressImage(String filePath) {

        //原文件
        File oldFile = new File(filePath);


        //压缩文件路径 照片路径/
        String targetPath = oldFile.getPath();
        int quality = 50;//压缩比例0-100
        Bitmap bm = getSmallBitmap(filePath);//获取一定尺寸的图片
        int degree = getRotateAngle(filePath);//获取相片拍摄角度

        if (degree != 0) {//旋转照片角度,防止头像横着显示
            bm = setRotateAngle(degree,bm);
        }
        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);
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
            return filePath;
        }
        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);
    }


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


}

//简单的封装了一下网络请求工具类RetorfitFactory

public class RetrofitFactory {

    private static RetrofitFactory mRetrofitFactory;
    private static  APIFunction mAPIFunction;
    private RetrofitFactory(){
        OkHttpClient mOkHttpClient=new OkHttpClient.Builder()
                .connectTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
                .readTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
                .writeTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)
                .build();
        Retrofit mRetrofit=new Retrofit.Builder()
                .baseUrl(HttpConfig.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())//添加gson转换器
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())//添加rxjava转换器
                .client(mOkHttpClient)
                .build();
        mAPIFunction=mRetrofit.create(APIFunction.class);

    }

    public static RetrofitFactory getInstence(){
        if (mRetrofitFactory==null){
            synchronized (RetrofitFactory.class) {
                if (mRetrofitFactory == null)
                    mRetrofitFactory = new RetrofitFactory();
            }

        }
        return mRetrofitFactory;
    }
    public  APIFunction API(){
        return mAPIFunction;
    }
}


代理API接口类APIFunction

/**
 * @author yemao
 * @date 2017/4/9
 * @description API接口!
 */

public interface APIFunction {


    //上传单张图片
    @POST("服务器地址")
    Observable<Object> imageUpload(@Part() MultipartBody.Part img);
    //上传多张图片
    @POST("服务器地址")
    Observable<Object> imagesUpload(@Part() List<MultipartBody.Part> imgs);
}


上传图片的的工具类

package com.yr.example.utils;

import android.content.Context;
import android.os.AsyncTask;

import com.yr.example.http.RetrofitFactory;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;

/**
 * @author yemao
 * @date 2017/4/17
 * @description null!
 */

public class UploadUtil {

    /**
     * 上传单张图片
     *
     * @param filePath 图片本地路径
     * @param observer 观察者
     * @throws IOException
     */
    public static void uploadImage(final String filePath, final Observer observer) {
        new AsyncTask<Integer, Integer, File>() {
            @Override
            protected File doInBackground(Integer... params) {
                //压缩图片
                File file = new File(BitmapUtil.compressImage(filePath));
                return file;
            }

            @Override
            protected void onPostExecute(File file) {
                super.onPostExecute(file);
                RequestBody requestBody = RequestBody.create(MediaType.parse("image/png"), file);
                MultipartBody.Part part = MultipartBody.Part.createFormData("file", file.getName(), requestBody);
                RetrofitFactory.getInstence().API()
                        .imageUpload( part)
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(observer);
            }
        }.execute();


    }

    /**
     * 上传多张照片
     *
     * @param mFilesPath 图片本地路径
     * @param observer
     */
    public static void uploadImages(final ArrayList<String> mFilesPath, final Observer observer) {
        new AsyncTask<Integer, Integer, List<File>>() {
            @Override
            protected List<File> doInBackground(Integer... params) {
                //压缩图片
                final List<File> files = new ArrayList<>();
                for (String path : mFilesPath) {
                    File file = new File(BitmapUtil.compressImage(path));
                    files.add(file);

                }
                return files;
            }

            @Override
            protected void onPostExecute(List<File> files) {
                super.onPostExecute(files);
                List<MultipartBody.Part> xx = filesToMultipartBodyParts(files);
                RetrofitFactory.getInstence().API()
                        .imagesUpload( xx)
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(observer);
            }
        }.execute();


    }

    /**
     * @param files 多图片文件转表单
     * @return
     */
    public static List<MultipartBody.Part> filesToMultipartBodyParts(List<File> files) {
        List<MultipartBody.Part> parts = new ArrayList<>(files.size());
        for (File file : files) {
            RequestBody requestBody = RequestBody.create(MediaType.parse("image/png"), file);
            MultipartBody.Part part = MultipartBody.Part.createFormData("files", file.getName(), requestBody);
            parts.add(part);
        }
        return parts;
    }
}


使用方法

上传单张图片

 
    public void upload(){
        String filepath="图片本地路径";
        UploadUtil.uploadImage(filepath, new Observer() {
            @Override
            public void onSubscribe(Disposable d) {
                
            }

            @Override
            public void onNext(Object o) {
                //返回结果
            }

            @Override
            public void onError(Throwable e) {
               //上传失败
            }

            @Override
            public void onComplete() {

            }
        });
    }


上传多张图片

public void uploads(){
        ArrayList<String> listFilePath=new ArrayList<>();
        listFilePath.add("图片1路径");
        listFilePath.add("图片2路径");
        UploadUtil.uploadImages(listFilePath, new Observer() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(Object o) {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });
    }


到了这里大功告成了哦!

猜你喜欢

转载自blog.csdn.net/yrmao9893/article/details/70599061