Android壓縮圖片後再上傳圖片

Dusan_杜小菜發表於2016-05-24

在Android開發中上傳圖片(頭像)到伺服器,要先壓縮圖片,獲取原圖的長寬,然後取得壓縮比例,compress到指定的質量,輸出儲存,然後網路上傳這張圖片就行了。之前分享了web前端壓縮圖片的方式:
web前端之HTML5壓縮圖片compress image with canvas
上傳頭像

1,乾言

如果圖片太大,上傳不僅耗時,而且體驗不好。即使加了loading效果,那還是挺耗流量的。so,果斷要壓縮圖片再上傳,android客戶端,尤其要注意。

2,圖片上傳

壓縮原圖後儲存在sdcard臨時目錄,如果壓縮後的圖片存在,就上傳壓縮的圖片,沒有壓縮成功(不存在),就直接上原圖吧。

// 壓縮圖片並上傳
 private  void uploadFileInThreadByOkHttp(final Activity context, final String actionUrl, final File tempPic) {
    final String pic_path = tempPic.getPath();
    String targetPath = FileUtils.getThumbDir()+"compressPic.jpg";
    //呼叫壓縮圖片的方法,返回壓縮後的圖片path
    final String compressImage = PictureUtil.compressImage(pic_path, targetPath, 30);
    final File compressedPic = new File(compressImage);
    if (compressedPic.exists()) {
      LogUtils.debug(TAG,"圖片壓縮上傳");
      uploadFileByOkHTTP(context, actionUrl, compressedPic);
   }else{//直接上傳
        uploadFileByOkHTTP(context, actionUrl, tempPic);
   }
}

3,壓縮圖片的關鍵程式碼

 public static String compressImage(String filePath, String targetPath, int quality)  {
          Bitmap bm = getSmallBitmap(filePath);//獲取一定尺寸的圖片
        int degree = readPictureDegree(filePath);//獲取相片拍攝角度
        if(degree!=0){//旋轉照片角度,防止頭像橫著顯示
            bm=rotateBitmap(bm,degree);
        }
        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);
        }catch (Exception e){}
        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);
    }


    /**
     * 獲取照片角度
     * @param path
     * @return
     */
    public static int readPictureDegree(String path) {
        int degree = 0;
        try {
            ExifInterface exifInterface = new ExifInterface(path);
            int orientation = exifInterface.getAttributeInt(
                    ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    degree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    degree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    degree = 270;
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return degree;
    }

    /**
     * 旋轉照片
     * @param bitmap
     * @param degress
     * @return
     */
    public static Bitmap rotateBitmap(Bitmap bitmap,int degress) {
        if (bitmap != null) {
            Matrix m = new Matrix();
            m.postRotate(degress);
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                    bitmap.getHeight(), m, true);
            return bitmap;
        }
        return bitmap;
    }
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;
    }

4,上傳圖片

使用okhttp,如果不太熟悉okhttp的話,可以看我的另一博文:
Android網路請求:OkHttp實戰
本文上傳頭像,封裝uploadFile方法如下:


    /**
     * 上傳檔案
     * @param url  介面地址
     * @param file 上傳的檔案
     * @param mediaType  資源mediaType型別:比如 MediaType.parse("image/png");
     * @param responseCallback 回撥方法,在子執行緒,更新UI要post到主執行緒
     * @return
     */
    public boolean uploadFile(String url, File file, MediaType mediaType, Callback responseCallback) {
        MultipartBody.Builder builder = new MultipartBody.Builder().setType(MediaType.parse("multipart/form-data"));
        if (!file.exists()|| TextUtils.isEmpty(url)){
            return false;
        }
        //addFormDataPart視專案自身的情況而定
               //builder.addFormDataPart("description","2.jpg");
        builder.addFormDataPart("file", file.getName(), RequestBody.create(mediaType, file));
        //構建請求體
        RequestBody requestBody = builder.build();
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();
        enqueue(request,responseCallback);
        return true;
    }

其中的RequestBody大概是這樣的:

MultipartBody.Builder builder = new MultipartBody.Builder().setType(MediaType.parse("multipart/form-data"));      builder.addFormDataPart("description","duqian.jpg");
builder.addFormDataPart("file", "Dusan.jpg", RequestBody.create(MEDIA_TYPE_PNG, new File(photoPath)));

5,over,休息

哈哈,簡單,如果遇到上傳檔案的格式限制,和後臺協調下。親測,圖片壓縮效果明顯,不影響清晰度。你也可以自己改質量,寬高,確定壓縮後的圖片,網路框架嘛,很多,看個人習慣咯。


歡迎交流,Dusan,291902259,OpenDeveloper。
需要android頂尖學習資料和VIP視訊的可以加我Q:291902259。

相關文章