1. 程式人生 > >(轉)Android學習-使用Async-Http實現圖片壓縮並上傳功能

(轉)Android學習-使用Async-Http實現圖片壓縮並上傳功能

activit 一次 make down cte hot for lfw ram

(轉)Android學習-使用Async-Http實現圖片壓縮並上傳功能


文章轉載自:
作者:RyaneLee
鏈接:http://www.jianshu.com/p/940fc7ba39e1

讓我頭疼一個星期的圖片批量上傳服務器的問題最後受這篇文章的作者啟發而解決,自己之前一直執著於通過uri地址找到圖片然後上傳圖片,卻沒想過直接上傳圖片本身。感謝作者的博客和啟發。

前言

(轉載請註明出處,謝謝!)

最近在做一個小項目,項目中要實現上傳圖片到服務器,而這個例子是實現圖片的尺寸壓縮,將獲取到的壓縮圖片轉為流,然後使用Async-Http開源框架實現圖片流的上傳,然後在服務器端將流寫入本地。

效果圖

技術分享

安卓端 技術分享
服務器端

解決

安卓端

一、點擊加載本地相冊選擇圖片,然後加載到ImageView中去,並獲取圖片地址以供後面圖片上傳時使用。

 1         //點擊圖片打開選擇圖片界面
 2     photo.setOnClickListener(new OnClickListener() {
 3 
 4         @Override
 5         public void onClick(View v) {
 6             //使用Intent觸發選擇Action
 7             Intent intent = new Intent(Intent.ACTION_PICK, null
); 8 //打開系統提供的圖片選擇界面 9 intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*"); 10 //傳參以在返回本界面時觸發加載圖片的功能 11 startActivityForResult(intent, 0x1); 12 } 13 });

 

 1 //在選擇圖片後返回本界面調用此方法
 2 @Override
 3 protected void onActivityResult(int
requestCode, int resultCode, Intent data) { 4 if (requestCode == 0x1 && resultCode == RESULT_OK) { 5 if (data != null) { 6 7 ContentResolver resolver = getContentResolver(); 8 try { 9 // 獲取圖片URI 10 Uri uri = data.getData(); 11 // 將URI轉換為路徑: 12 String[] proj = { MediaStore.Images.Media.DATA }; 13 Cursor cursor = managedQuery(uri, proj, null, null, null); 14 // 這個是獲得用戶選擇的圖片的索引值 15 int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); 16 cursor.moveToFirst(); 17 // 最後根據索引值獲取圖片路徑 18 photoPath = cursor.getString(column_index); 19 20 // 壓縮成800*480 21 bitmap = BitmapUtils.decodeSampledBitmapFromFd(photoPath, 480, 800); 22 // 設置imageview顯示圖片 23 photo.setImageBitmap(bitmap); 24 // 設置textview顯示路徑 25 path.setText(photoPath); 26 } catch (Exception e) { 27 e.printStackTrace(); 28 } 29 30 } 31 } 32 }

 

二、圖片壓縮。在我們需要上傳圖片時,我們不可能直接把原圖上傳到服務器,因為一般圖片的大小都超過3,4M,所以我們在上傳之前需要對圖片進行壓縮,我是把圖片壓縮放到了一個工具類,主要是對圖片進行尺寸壓縮。

 1 public class BitmapUtils {
 2 
 3     private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
 4         final int height = options.outHeight;
 5         final int width = options.outWidth;
 6         int inSampleSize = 1;
 7         if (height > reqHeight || width > reqWidth) {
 8             //首先獲取原圖高度和寬度的一半
 9             final int halfHeight = height / 2;
10             final int halfWidth = width / 2;
11             //循環,如果halfHeight和halfWidth同時大於最小寬度和最小高度時,inSampleSize乘2,
12             //最後得到的寬或者高都是最接近最小寬度或者最小高度的
13             while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) {
14                 inSampleSize *= 2;
15             }
16         }
17         return inSampleSize;
18     }
19 
20     /**
21      * 根據Resources壓縮圖片
22      * 
23      * @param res
24      * @param resId
25      * @param reqWidth
26      * @param reqHeight
27      * @return
28      */
29     public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {
30         final BitmapFactory.Options options = new BitmapFactory.Options();
31         options.inJustDecodeBounds = true;
32         BitmapFactory.decodeResource(res, resId, options);
33         options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
34         options.inJustDecodeBounds = false;
35         Bitmap src = BitmapFactory.decodeResource(res, resId, options);
36         return src;
37     }
38 
39     /**
40      * 根據地址壓縮圖片
41      * 
42      * @param pathName
43      * @param reqWidth 最小寬度
44      * @param reqHeight 最小高度
45      * @return
46      */
47     public static Bitmap decodeSampledBitmapFromFd(String pathName, int reqWidth, int reqHeight) {
48         final BitmapFactory.Options options = new BitmapFactory.Options();
49         // 若要對圖片進行壓縮,必須先設置Option的inJustDecodeBounds為true才能進行Option的修改
50         options.inJustDecodeBounds = true;
51         // 第一次decodeFile是獲取到options.outHeight和options.outWidth
52         BitmapFactory.decodeFile(pathName, options);
53         // options.inSampleSize是圖片的壓縮比,例如原來大小是100*100,options.inSampleSize為1,則不變,
54         // options.inSampleSize為2,則壓縮成50*50
55         options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
56         // 重新設置options.inJustDecodeBounds為false,不能修改option
57         options.inJustDecodeBounds = false;
58         // 根據options重新加載圖片
59         Bitmap src = BitmapFactory.decodeFile(pathName, options);
60         return src;
61     }
62 }

 

三、將Bitmap轉為String,同時使用BASE64加密,使傳輸更加安全,這是我的工具類,裏面再一次進行壓縮是質量壓縮,壓縮比例是30%,具體自己調

 1 public class Utils {
 2     // 將bitmap轉成string類型通過Base64
 3     public static String BitmapToString(Bitmap bitmap) {
 4 
 5         ByteArrayOutputStream bao = new ByteArrayOutputStream();
 6         // 將bitmap壓縮成30%
 7         bitmap.compress(Bitmap.CompressFormat.JPEG, 30, bao);
 8         // 將bitmap轉化為一個byte數組
 9         byte[] bs = bao.toByteArray();
10         // 將byte數組用BASE64加密
11         String photoStr = Base64.encodeToString(bs, Base64.DEFAULT);
12         // 返回String
13         return photoStr;
14     }
15 }

 

四、通過Async-Http實現圖片上傳

 1  public void upload(String url) {
 2         // 將bitmap轉為string,並使用BASE64加密
 3         String photo = Utils.BitmapToString(bitmap);
 4         // 獲取到圖片的名字
 5         String name = photoPath.substring(photoPath.lastIndexOf("/")).substring(1);
 6         // new一個請求參數
 7         RequestParams params = new RequestParams();
 8         // 將圖片和名字添加到參數中
 9         params.put("photo", photo);
10         params.put("name", name);
11         AsyncHttpClient client = new AsyncHttpClient();
12         // 調用AsyncHttpClient的post方法
13         client.post(url, params, new AsyncHttpResponseHandler() {
14 
15             @Override
16             public void onFailure(int arg0, Header[] arg1, byte[] arg2, Throwable arg3) {
17                 Toast.makeText(getApplicationContext(), "上傳失敗!", Toast.LENGTH_SHORT).show();
18             }
19 
20             @Override
21             public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {
22                 Toast.makeText(getApplicationContext(), "上傳成功!", Toast.LENGTH_SHORT).show();
23             }
24         });
25     }

服務器端

一、創建一個新的Servlet,在doget方法裏面實現

 1 public class UpLoadPhotoServlet extends HttpServlet {
 2     /**
 3      * 
 4      */
 5     private static final long serialVersionUID = 1L;
 6 
 7     public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 8         request.setCharacterEncoding("utf-8");
 9         response.setCharacterEncoding("utf-8");
10         response.setContentType("text/html");
11         // 獲取文件名
12         String name = request.getParameter("name");
13         // 獲取圖片
14         String photo = request.getParameter("photo");
15         // 將傳進來的圖片的string格式進行處理
16         byte[] bs = new BASE64Decoder().decodeBuffer(photo);
17         // 寫到E盤Img文件夾下的a.jpg文件。註:Img文件夾一定要存在
18         FileOutputStream fos = new FileOutputStream("E:/Img/" + name);
19         fos.write(bs);
20         fos.flush();
21         fos.close();
22 
23         PrintWriter writer = response.getWriter();
24         writer.print("上傳成功");
25     }
26 
27     @Override
28     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
29         doGet(req, resp);
30     }
31 }

 

Demo地址

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



(轉)Android學習-使用Async-Http實現圖片壓縮並上傳功能