(轉載請註明出處,謝謝!)
最近在作一個小項目,項目中要實現上傳圖片到服務器,而這個例子是實現圖片的尺寸壓縮,將獲取到的壓縮圖片轉爲流,而後使用Async-Http開源框架實現圖片流的上傳,而後在服務器端將流寫入本地。html
效果圖java
安卓端數組
服務器端安全
1、點擊加載本地相冊選擇圖片,而後加載到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(); } } } }
2、圖片壓縮。在咱們須要上傳圖片時,咱們不可能直接把原圖上傳到服務器,由於通常圖片的大小都超過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; } }
3、將Bitmap轉爲String,同時使用BASE64加密,使傳輸更加安全,這是個人工具類,裏面再一次進行壓縮是質量壓縮,壓縮比例是30%,具體本身調。ide
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; } }
4、經過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(); } }); }
1、建立一個新的Servlet,在doget方法裏面實現post
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); } }