首页 > 系统 > Android > 正文

Android选择图片或拍照图片上传到服务器

2019-12-12 04:03:28
字体:
来源:转载
供稿:网友

最近要搞一个项目,需要上传相册和拍照的图片,不负所望,终于完成了!  不过需要说明一下,其实网上很多教程拍照的图片,都是缩略图不是很清晰,所以需要在调用照相机的时候,事先生成一个地址,用于标识拍照的图片URI

具体上传代码:

1.选择图片和上传界面,包括上传完成和异常的回调监听

package com.spring.sky.image.upload;   import java.util.HashMap; import java.util.Map;  import android.app.Activity; import android.app.ProgressDialog; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast;  import com.spring.sky.image.upload.network.UploadUtil; import com.spring.sky.image.upload.network.UploadUtil.OnUploadProcessListener; /**  * @author spring sky<br>  * Email :vipa1888@163.com<br>  * QQ: 840950105<br>  * 说明:主要用于选择文件和上传文件操作  */ public class MainActivity extends Activity implements OnClickListener,OnUploadProcessListener{  private static final String TAG = "uploadImage";    /**   * 去上传文件   */  protected static final int TO_UPLOAD_FILE = 1;  /**   * 上传文件响应   */  protected static final int UPLOAD_FILE_DONE = 2; //  /**   * 选择文件   */  public static final int TO_SELECT_PHOTO = 3;  /**   * 上传初始化   */  private static final int UPLOAD_INIT_PROCESS = 4;  /**   * 上传中   */  private static final int UPLOAD_IN_PROCESS = 5;  /***   * 这里的这个URL是我服务器的javaEE环境URL   */  private static String requestURL = "http://192.168.10.160:8080/fileUpload/p/file!upload";  private Button selectButton,uploadButton;  private ImageView imageView;  private TextView uploadImageResult;  private ProgressBar progressBar;    private String picPath = null;  private ProgressDialog progressDialog;    /** Called when the activity is first created. */  @Override  public void onCreate(Bundle savedInstanceState) {   super.onCreate(savedInstanceState);   setContentView(R.layout.main);   initView();  }    /**   * 初始化数据   */  private void initView() {   selectButton = (Button) this.findViewById(R.id.selectImage);   uploadButton = (Button) this.findViewById(R.id.uploadImage);   selectButton.setOnClickListener(this);   uploadButton.setOnClickListener(this);   imageView = (ImageView) this.findViewById(R.id.imageView);   uploadImageResult = (TextView) findViewById(R.id.uploadImageResult);   progressDialog = new ProgressDialog(this);   progressBar = (ProgressBar) findViewById(R.id.progressBar1);  }   @Override  public void onClick(View v) {   switch (v.getId()) {   case R.id.selectImage:    Intent intent = new Intent(this,SelectPicActivity.class);    startActivityForResult(intent, TO_SELECT_PHOTO);    break;   case R.id.uploadImage:    if(picPath!=null)    {     handler.sendEmptyMessage(TO_UPLOAD_FILE);    }else{     Toast.makeText(this, "上传的文件路径出错", Toast.LENGTH_LONG).show();    }    break;   default:    break;   }  }   @Override  protected void onActivityResult(int requestCode, int resultCode, Intent data) {   if(resultCode==Activity.RESULT_OK && requestCode == TO_SELECT_PHOTO)   {    picPath = data.getStringExtra(SelectPicActivity.KEY_PHOTO_PATH);    Log.i(TAG, "最终选择的图片="+picPath);    Bitmap bm = BitmapFactory.decodeFile(picPath);    imageView.setImageBitmap(bm);   }   super.onActivityResult(requestCode, resultCode, data);  }     /**   * 上传服务器响应回调   */  @Override  public void onUploadDone(int responseCode, String message) {   progressDialog.dismiss();   Message msg = Message.obtain();   msg.what = UPLOAD_FILE_DONE;   msg.arg1 = responseCode;   msg.obj = message;   handler.sendMessage(msg);  }    private void toUploadFile()  {   uploadImageResult.setText("正在上传中...");   progressDialog.setMessage("正在上传文件...");   progressDialog.show();   String fileKey = "pic";   UploadUtil uploadUtil = UploadUtil.getInstance();;   uploadUtil.setOnUploadProcessListener(this); //设置监听器监听上传状态      Map<String, String> params = new HashMap<String, String>();   params.put("orderId", "11111");   uploadUtil.uploadFile( picPath,fileKey, requestURL,params);  }    private Handler handler = new Handler(){   @Override   public void handleMessage(Message msg) {    switch (msg.what) {    case TO_UPLOAD_FILE:     toUploadFile();     break;        case UPLOAD_INIT_PROCESS:     progressBar.setMax(msg.arg1);     break;    case UPLOAD_IN_PROCESS:     progressBar.setProgress(msg.arg1);     break;    case UPLOAD_FILE_DONE:     String result = "响应码:"+msg.arg1+"/n响应信息:"+msg.obj+"/n耗时:"+UploadUtil.getRequestTime()+"秒";     uploadImageResult.setText(result);     break;    default:     break;    }    super.handleMessage(msg);   }     };   @Override  public void onUploadProcess(int uploadSize) {   Message msg = Message.obtain();   msg.what = UPLOAD_IN_PROCESS;   msg.arg1 = uploadSize;   handler.sendMessage(msg );  }   @Override  public void initUpload(int fileSize) {   Message msg = Message.obtain();   msg.what = UPLOAD_INIT_PROCESS;   msg.arg1 = fileSize;   handler.sendMessage(msg );  }   } 

2.选择图片界面,主要涉及两种方式:选择图片和及时拍照图片

package com.spring.sky.image.upload;  import android.app.Activity; import android.content.ContentValues; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.LinearLayout; import android.widget.Toast;  /**  * @author spring sky<br>  * Email :vipa1888@163.com<br>  * QQ: 840950105<br>  * @version 创建时间:2012-11-22 上午9:20:03  * 说明:主要用于选择文件操作  */  public class SelectPicActivity extends Activity implements OnClickListener{   /***   * 使用照相机拍照获取图片   */  public static final int SELECT_PIC_BY_TACK_PHOTO = 1;  /***   * 使用相册中的图片   */  public static final int SELECT_PIC_BY_PICK_PHOTO = 2;    /***   * 从Intent获取图片路径的KEY   */  public static final String KEY_PHOTO_PATH = "photo_path";    private static final String TAG = "SelectPicActivity";    private LinearLayout dialogLayout;  private Button takePhotoBtn,pickPhotoBtn,cancelBtn;   /**获取到的图片路径*/  private String picPath;    private Intent lastIntent ;    private Uri photoUri;  @Override  protected void onCreate(Bundle savedInstanceState) {   super.onCreate(savedInstanceState);   setContentView(R.layout.select_pic_layout);   initView();  }  /**   * 初始化加载View   */  private void initView() {   dialogLayout = (LinearLayout) findViewById(R.id.dialog_layout);   dialogLayout.setOnClickListener(this);   takePhotoBtn = (Button) findViewById(R.id.btn_take_photo);   takePhotoBtn.setOnClickListener(this);   pickPhotoBtn = (Button) findViewById(R.id.btn_pick_photo);   pickPhotoBtn.setOnClickListener(this);   cancelBtn = (Button) findViewById(R.id.btn_cancel);   cancelBtn.setOnClickListener(this);      lastIntent = getIntent();  }   @Override  public void onClick(View v) {   switch (v.getId()) {   case R.id.dialog_layout:    finish();    break;   case R.id.btn_take_photo:    takePhoto();    break;   case R.id.btn_pick_photo:    pickPhoto();    break;   default:    finish();    break;   }  }   /**   * 拍照获取图片   */  private void takePhoto() {   //执行拍照前,应该先判断SD卡是否存在   String SDState = Environment.getExternalStorageState();   if(SDState.equals(Environment.MEDIA_MOUNTED))   {        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);//"android.media.action.IMAGE_CAPTURE"    /***     * 需要说明一下,以下操作使用照相机拍照,拍照后的图片会存放在相册中的     * 这里使用的这种方式有一个好处就是获取的图片是拍照后的原图     * 如果不实用ContentValues存放照片路径的话,拍照后获取的图片为缩略图不清晰     */    ContentValues values = new ContentValues();    photoUri = this.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);    intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, photoUri);    /**-----------------*/    startActivityForResult(intent, SELECT_PIC_BY_TACK_PHOTO);   }else{    Toast.makeText(this,"内存卡不存在", Toast.LENGTH_LONG).show();   }  }   /***   * 从相册中取图片   */  private void pickPhoto() {   Intent intent = new Intent();   intent.setType("image/*");   intent.setAction(Intent.ACTION_GET_CONTENT);   startActivityForResult(intent, SELECT_PIC_BY_PICK_PHOTO);  }    @Override  public boolean onTouchEvent(MotionEvent event) {   finish();   return super.onTouchEvent(event);  }      @Override  protected void onActivityResult(int requestCode, int resultCode, Intent data) {   if(resultCode == Activity.RESULT_OK)   {    doPhoto(requestCode,data);   }   super.onActivityResult(requestCode, resultCode, data);  }    /**   * 选择图片后,获取图片的路径   * @param requestCode   * @param data   */  private void doPhoto(int requestCode,Intent data)  {   if(requestCode == SELECT_PIC_BY_PICK_PHOTO ) //从相册取图片,有些手机有异常情况,请注意   {    if(data == null)    {     Toast.makeText(this, "选择图片文件出错", Toast.LENGTH_LONG).show();     return;    }    photoUri = data.getData();    if(photoUri == null )    {     Toast.makeText(this, "选择图片文件出错", Toast.LENGTH_LONG).show();     return;    }   }   String[] pojo = {MediaStore.Images.Media.DATA};   Cursor cursor = managedQuery(photoUri, pojo, null, null,null);    if(cursor != null )   {    int columnIndex = cursor.getColumnIndexOrThrow(pojo[0]);    cursor.moveToFirst();    picPath = cursor.getString(columnIndex);    cursor.close();   }   Log.i(TAG, "imagePath = "+picPath);   if(picPath != null && ( picPath.endsWith(".png") || picPath.endsWith(".PNG") ||picPath.endsWith(".jpg") ||picPath.endsWith(".JPG") ))   {    lastIntent.putExtra(KEY_PHOTO_PATH, picPath);    setResult(Activity.RESULT_OK, lastIntent);    finish();   }else{    Toast.makeText(this, "选择图片文件不正确", Toast.LENGTH_LONG).show();   }  } } 

3. 上传工具类,主要实现了图片的上传,上传过程的初始化监听和上传完成的监听,还有上传耗时的计算

package com.spring.sky.image.upload.network;  import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.Iterator; import java.util.Map; import java.util.UUID;  import android.util.Log;  /**  *  * 上传工具类  * @author spring sky<br>  * Email :vipa1888@163.com<br>  * QQ: 840950105<br>  * 支持上传文件和参数  */ public class UploadUtil {  private static UploadUtil uploadUtil;  private static final String BOUNDARY = UUID.randomUUID().toString(); // 边界标识 随机生成  private static final String PREFIX = "--";  private static final String LINE_END = "/r/n";  private static final String CONTENT_TYPE = "multipart/form-data"; // 内容类型  private UploadUtil() {   }   /**   * 单例模式获取上传工具类   * @return   */  public static UploadUtil getInstance() {   if (null == uploadUtil) {    uploadUtil = new UploadUtil();   }   return uploadUtil;  }   private static final String TAG = "UploadUtil";  private int readTimeOut = 10 * 1000; // 读取超时  private int connectTimeout = 10 * 1000; // 超时时间  /***   * 请求使用多长时间   */  private static int requestTime = 0;    private static final String CHARSET = "utf-8"; // 设置编码   /***   * 上传成功   */  public static final int UPLOAD_SUCCESS_CODE = 1;  /**   * 文件不存在   */  public static final int UPLOAD_FILE_NOT_EXISTS_CODE = 2;  /**   * 服务器出错   */  public static final int UPLOAD_SERVER_ERROR_CODE = 3;  protected static final int WHAT_TO_UPLOAD = 1;  protected static final int WHAT_UPLOAD_DONE = 2;    /**   * android上传文件到服务器   *   * @param filePath   *   需要上传的文件的路径   * @param fileKey   *   在网页上<input type=file name=xxx/> xxx就是这里的fileKey   * @param RequestURL   *   请求的URL   */  public void uploadFile(String filePath, String fileKey, String RequestURL,    Map<String, String> param) {   if (filePath == null) {    sendMessage(UPLOAD_FILE_NOT_EXISTS_CODE,"文件不存在");    return;   }   try {    File file = new File(filePath);    uploadFile(file, fileKey, RequestURL, param);   } catch (Exception e) {    sendMessage(UPLOAD_FILE_NOT_EXISTS_CODE,"文件不存在");    e.printStackTrace();    return;   }  }   /**   * android上传文件到服务器   *   * @param file   *   需要上传的文件   * @param fileKey   *   在网页上<input type=file name=xxx/> xxx就是这里的fileKey   * @param RequestURL   *   请求的URL   */  public void uploadFile(final File file, final String fileKey,    final String RequestURL, final Map<String, String> param) {   if (file == null || (!file.exists())) {    sendMessage(UPLOAD_FILE_NOT_EXISTS_CODE,"文件不存在");    return;   }    Log.i(TAG, "请求的URL=" + RequestURL);   Log.i(TAG, "请求的fileName=" + file.getName());   Log.i(TAG, "请求的fileKey=" + fileKey);   new Thread(new Runnable() { //开启线程上传文件    @Override    public void run() {     toUploadFile(file, fileKey, RequestURL, param);    }   }).start();     }   private void toUploadFile(File file, String fileKey, String RequestURL,    Map<String, String> param) {   String result = null;   requestTime= 0;      long requestTime = System.currentTimeMillis();   long responseTime = 0;    try {    URL url = new URL(RequestURL);    HttpURLConnection conn = (HttpURLConnection) url.openConnection();    conn.setReadTimeout(readTimeOut);    conn.setConnectTimeout(connectTimeout);    conn.setDoInput(true); // 允许输入流    conn.setDoOutput(true); // 允许输出流    conn.setUseCaches(false); // 不允许使用缓存    conn.setRequestMethod("POST"); // 请求方式    conn.setRequestProperty("Charset", CHARSET); // 设置编码    conn.setRequestProperty("connection", "keep-alive");    conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");    conn.setRequestProperty("Content-Type", CONTENT_TYPE + ";boundary=" + BOUNDARY); //   conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");        /**     * 当文件不为空,把文件包装并且上传     */    DataOutputStream dos = new DataOutputStream(conn.getOutputStream());    StringBuffer sb = null;    String params = "";        /***     * 以下是用于上传参数     */    if (param != null && param.size() > 0) {     Iterator<String> it = param.keySet().iterator();     while (it.hasNext()) {      sb = null;      sb = new StringBuffer();      String key = it.next();      String value = param.get(key);      sb.append(PREFIX).append(BOUNDARY).append(LINE_END);      sb.append("Content-Disposition: form-data; name=/"").append(key).append("/"").append(LINE_END).append(LINE_END);      sb.append(value).append(LINE_END);      params = sb.toString();      Log.i(TAG, key+"="+params+"##");      dos.write(params.getBytes()); //     dos.flush();     }    }        sb = null;    params = null;    sb = new StringBuffer();    /**     * 这里重点注意: name里面的值为服务器端需要key 只有这个key 才可以得到对应的文件     * filename是文件的名字,包含后缀名的 比如:abc.png     */    sb.append(PREFIX).append(BOUNDARY).append(LINE_END);    sb.append("Content-Disposition:form-data; name=/"" + fileKey      + "/"; filename=/"" + file.getName() + "/"" + LINE_END);    sb.append("Content-Type:image/pjpeg" + LINE_END); // 这里配置的Content-type很重要的 ,用于服务器端辨别文件的类型的    sb.append(LINE_END);    params = sb.toString();    sb = null;        Log.i(TAG, file.getName()+"=" + params+"##");    dos.write(params.getBytes());    /**上传文件*/    InputStream is = new FileInputStream(file);    onUploadProcessListener.initUpload((int)file.length());    byte[] bytes = new byte[1024];    int len = 0;    int curLen = 0;    while ((len = is.read(bytes)) != -1) {     curLen += len;     dos.write(bytes, 0, len);     onUploadProcessListener.onUploadProcess(curLen);    }    is.close();        dos.write(LINE_END.getBytes());    byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINE_END).getBytes();    dos.write(end_data);    dos.flush(); //   //   dos.write(tempOutputStream.toByteArray());    /**     * 获取响应码 200=成功 当响应成功,获取响应的流     */    int res = conn.getResponseCode();    responseTime = System.currentTimeMillis();    this.requestTime = (int) ((responseTime-requestTime)/1000);    Log.e(TAG, "response code:" + res);    if (res == 200) {     Log.e(TAG, "request success");     InputStream input = conn.getInputStream();     StringBuffer sb1 = new StringBuffer();     int ss;     while ((ss = input.read()) != -1) {      sb1.append((char) ss);     }     result = sb1.toString();     Log.e(TAG, "result : " + result);     sendMessage(UPLOAD_SUCCESS_CODE, "上传结果:"       + result);     return;    } else {     Log.e(TAG, "request error");     sendMessage(UPLOAD_SERVER_ERROR_CODE,"上传失败:code=" + res);     return;    }   } catch (MalformedURLException e) {    sendMessage(UPLOAD_SERVER_ERROR_CODE,"上传失败:error=" + e.getMessage());    e.printStackTrace();    return;   } catch (IOException e) {    sendMessage(UPLOAD_SERVER_ERROR_CODE,"上传失败:error=" + e.getMessage());    e.printStackTrace();    return;   }  }   /**   * 发送上传结果   * @param responseCode   * @param responseMessage   */  private void sendMessage(int responseCode,String responseMessage)  {   onUploadProcessListener.onUploadDone(responseCode, responseMessage);  }    /**   * 下面是一个自定义的回调函数,用到回调上传文件是否完成   *   * @author shimingzheng   *   */  public static interface OnUploadProcessListener {   /**    * 上传响应    * @param responseCode    * @param message    */   void onUploadDone(int responseCode, String message);   /**    * 上传中    * @param uploadSize    */   void onUploadProcess(int uploadSize);   /**    * 准备上传    * @param fileSize    */   void initUpload(int fileSize);  }  private OnUploadProcessListener onUploadProcessListener;       public void setOnUploadProcessListener(    OnUploadProcessListener onUploadProcessListener) {   this.onUploadProcessListener = onUploadProcessListener;  }   public int getReadTimeOut() {   return readTimeOut;  }   public void setReadTimeOut(int readTimeOut) {   this.readTimeOut = readTimeOut;  }   public int getConnectTimeout() {   return connectTimeout;  }   public void setConnectTimeout(int connectTimeout) {   this.connectTimeout = connectTimeout;  }  /**   * 获取上传使用的时间   * @return   */  public static int getRequestTime() {   return requestTime;  }    public static interface uploadProcessListener{     }         } 

以上代码,我就不详细讲解原理,相关难点注释已经写得很清楚了!分享出来,和大家一起学习!

相关服务器端代码和客户端下载:
android客户端下载
javaEE服务器端

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表