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

转自:http://write.blog.csdn.net/postedit/70599061

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

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

  • 质量压缩
  • 采样率压缩
  • 缩放法压缩
  • RGB_565
  • createScaledBitmap

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

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

压缩前的图片截图:
Android实现图片压缩并上传到服务器_第1张图片
点击其中一张图片
Android实现图片压缩并上传到服务器_第2张图片
上传并压缩后的截图
Android实现图片压缩并上传到服务器_第3张图片
点击其中一张小图
Android实现图片压缩并上传到服务器_第4张图片
在送一张好图
Android实现图片压缩并上传到服务器_第5张图片
由肉眼辨别,貌似压缩前和压缩后的分辨率·,没有什么区别。

我也简单的做了一下对比,压缩前图片的大小为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 imageUpload(@Part() MultipartBody.Part img);
    //上传多张图片
    @POST("服务器地址")
    Observable imagesUpload(@Part() List 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() {
            @Override
            protected File doInBackground(Integer... params) {
                //压缩图片
                File file = new File(BitmapUtil.compressImage(filePath));
                return null;
            }
 
            @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 mFilesPath, final Observer observer) {
        new AsyncTask>() {
            @Override
            protected List doInBackground(Integer... params) {
                //压缩图片
                final List files = new ArrayList<>();
                for (String path : mFilesPath) {
                    File file = new File(BitmapUtil.compressImage(path));
                    files.add(file);
 
                }
                return files;
            }
 
            @Override
            protected void onPostExecute(List files) {
                super.onPostExecute(files);
                List xx = filesToMultipartBodyParts(files);
                RetrofitFactory.getInstence().API()
                        .imagesUpload( xx)
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(observer);
            }
        }.execute();
 
 
    }
 
    /**
     * @param files 多图片文件转表单
     * @return
     */
    public static List filesToMultipartBodyParts(List files) {
        List 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 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() {
 
            }
        });
    }

到了这里就大功告成了!

你可能感兴趣的:(Android实现图片压缩并上传到服务器)