Android选择图片或拍照图片上传到服务器
最近要搞一个项目,需要上传相册和拍照的图片,不负所望,终于完成了! 不过需要说明一下,其实网上很多教程拍照的图片,都是缩略图不是很清晰,所以需要在调用照相机的时候,事先生成一个地址,用于标识拍照的图片URI
具体上传代码:
1.选择图片和上传界面,包括上传完成和异常的回调监听
packagecom.spring.sky.image.upload;
importjava.util.HashMap;
importjava.util.Map;
importandroid.app.Activity;
importandroid.app.ProgressDialog;
importandroid.content.Intent;
importandroid.graphics.Bitmap;
importandroid.graphics.BitmapFactory;
importandroid.os.Bundle;
importandroid.os.Handler;
importandroid.os.Message;
importandroid.util.Log;
importandroid.view.View;
importandroid.view.View.OnClickListener;
importandroid.widget.Button;
importandroid.widget.ImageView;
importandroid.widget.ProgressBar;
importandroid.widget.TextView;
importandroid.widget.Toast;
importcom.spring.sky.image.upload.network.UploadUtil;
importcom.spring.sky.image.upload.network.UploadUtil.OnUploadProcessListener;
/**
*@authorspringsky<br>
*Email:vipa1888@163.com<br>
*QQ:840950105<br>
*说明:主要用于选择文件和上传文件操作
*/
publicclassMainActivityextendsActivityimplementsOnClickListener,OnUploadProcessListener{
privatestaticfinalStringTAG="uploadImage";
/**
*去上传文件
*/
protectedstaticfinalintTO_UPLOAD_FILE=1;
/**
*上传文件响应
*/
protectedstaticfinalintUPLOAD_FILE_DONE=2;//
/**
*选择文件
*/
publicstaticfinalintTO_SELECT_PHOTO=3;
/**
*上传初始化
*/
privatestaticfinalintUPLOAD_INIT_PROCESS=4;
/**
*上传中
*/
privatestaticfinalintUPLOAD_IN_PROCESS=5;
/***
*这里的这个URL是我服务器的javaEE环境URL
*/
privatestaticStringrequestURL="http://192.168.10.160:8080/fileUpload/p/file!upload";
privateButtonselectButton,uploadButton;
privateImageViewimageView;
privateTextViewuploadImageResult;
privateProgressBarprogressBar;
privateStringpicPath=null;
privateProgressDialogprogressDialog;
/**Calledwhentheactivityisfirstcreated.*/
@Override
publicvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initView();
}
/**
*初始化数据
*/
privatevoidinitView(){
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=newProgressDialog(this);
progressBar=(ProgressBar)findViewById(R.id.progressBar1);
}
@Override
publicvoidonClick(Viewv){
switch(v.getId()){
caseR.id.selectImage:
Intentintent=newIntent(this,SelectPicActivity.class);
startActivityForResult(intent,TO_SELECT_PHOTO);
break;
caseR.id.uploadImage:
if(picPath!=null)
{
handler.sendEmptyMessage(TO_UPLOAD_FILE);
}else{
Toast.makeText(this,"上传的文件路径出错",Toast.LENGTH_LONG).show();
}
break;
default:
break;
}
}
@Override
protectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){
if(resultCode==Activity.RESULT_OK&&requestCode==TO_SELECT_PHOTO)
{
picPath=data.getStringExtra(SelectPicActivity.KEY_PHOTO_PATH);
Log.i(TAG,"最终选择的图片="+picPath);
Bitmapbm=BitmapFactory.decodeFile(picPath);
imageView.setImageBitmap(bm);
}
super.onActivityResult(requestCode,resultCode,data);
}
/**
*上传服务器响应回调
*/
@Override
publicvoidonUploadDone(intresponseCode,Stringmessage){
progressDialog.dismiss();
Messagemsg=Message.obtain();
msg.what=UPLOAD_FILE_DONE;
msg.arg1=responseCode;
msg.obj=message;
handler.sendMessage(msg);
}
privatevoidtoUploadFile()
{
uploadImageResult.setText("正在上传中...");
progressDialog.setMessage("正在上传文件...");
progressDialog.show();
StringfileKey="pic";
UploadUtiluploadUtil=UploadUtil.getInstance();;
uploadUtil.setOnUploadProcessListener(this);//设置监听器监听上传状态
Map<String,String>params=newHashMap<String,String>();
params.put("orderId","11111");
uploadUtil.uploadFile(picPath,fileKey,requestURL,params);
}
privateHandlerhandler=newHandler(){
@Override
publicvoidhandleMessage(Messagemsg){
switch(msg.what){
caseTO_UPLOAD_FILE:
toUploadFile();
break;
caseUPLOAD_INIT_PROCESS:
progressBar.setMax(msg.arg1);
break;
caseUPLOAD_IN_PROCESS:
progressBar.setProgress(msg.arg1);
break;
caseUPLOAD_FILE_DONE:
Stringresult="响应码:"+msg.arg1+"\n响应信息:"+msg.obj+"\n耗时:"+UploadUtil.getRequestTime()+"秒";
uploadImageResult.setText(result);
break;
default:
break;
}
super.handleMessage(msg);
}
};
@Override
publicvoidonUploadProcess(intuploadSize){
Messagemsg=Message.obtain();
msg.what=UPLOAD_IN_PROCESS;
msg.arg1=uploadSize;
handler.sendMessage(msg);
}
@Override
publicvoidinitUpload(intfileSize){
Messagemsg=Message.obtain();
msg.what=UPLOAD_INIT_PROCESS;
msg.arg1=fileSize;
handler.sendMessage(msg);
}
}
2.选择图片界面,主要涉及两种方式:选择图片和及时拍照图片
packagecom.spring.sky.image.upload;
importandroid.app.Activity;
importandroid.content.ContentValues;
importandroid.content.Intent;
importandroid.database.Cursor;
importandroid.net.Uri;
importandroid.os.Bundle;
importandroid.os.Environment;
importandroid.provider.MediaStore;
importandroid.util.Log;
importandroid.view.MotionEvent;
importandroid.view.View;
importandroid.view.View.OnClickListener;
importandroid.widget.Button;
importandroid.widget.LinearLayout;
importandroid.widget.Toast;
/**
*@authorspringsky<br>
*Email:vipa1888@163.com<br>
*QQ:840950105<br>
*@version创建时间:2012-11-22上午9:20:03
*说明:主要用于选择文件操作
*/
publicclassSelectPicActivityextendsActivityimplementsOnClickListener{
/***
*使用照相机拍照获取图片
*/
publicstaticfinalintSELECT_PIC_BY_TACK_PHOTO=1;
/***
*使用相册中的图片
*/
publicstaticfinalintSELECT_PIC_BY_PICK_PHOTO=2;
/***
*从Intent获取图片路径的KEY
*/
publicstaticfinalStringKEY_PHOTO_PATH="photo_path";
privatestaticfinalStringTAG="SelectPicActivity";
privateLinearLayoutdialogLayout;
privateButtontakePhotoBtn,pickPhotoBtn,cancelBtn;
/**获取到的图片路径*/
privateStringpicPath;
privateIntentlastIntent;
privateUriphotoUri;
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.select_pic_layout);
initView();
}
/**
*初始化加载View
*/
privatevoidinitView(){
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
publicvoidonClick(Viewv){
switch(v.getId()){
caseR.id.dialog_layout:
finish();
break;
caseR.id.btn_take_photo:
takePhoto();
break;
caseR.id.btn_pick_photo:
pickPhoto();
break;
default:
finish();
break;
}
}
/**
*拍照获取图片
*/
privatevoidtakePhoto(){
//执行拍照前,应该先判断SD卡是否存在
StringSDState=Environment.getExternalStorageState();
if(SDState.equals(Environment.MEDIA_MOUNTED))
{
Intentintent=newIntent(MediaStore.ACTION_IMAGE_CAPTURE);//"android.media.action.IMAGE_CAPTURE"
/***
*需要说明一下,以下操作使用照相机拍照,拍照后的图片会存放在相册中的
*这里使用的这种方式有一个好处就是获取的图片是拍照后的原图
*如果不实用ContentValues存放照片路径的话,拍照后获取的图片为缩略图不清晰
*/
ContentValuesvalues=newContentValues();
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();
}
}
/***
*从相册中取图片
*/
privatevoidpickPhoto(){
Intentintent=newIntent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(intent,SELECT_PIC_BY_PICK_PHOTO);
}
@Override
publicbooleanonTouchEvent(MotionEventevent){
finish();
returnsuper.onTouchEvent(event);
}
@Override
protectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){
if(resultCode==Activity.RESULT_OK)
{
doPhoto(requestCode,data);
}
super.onActivityResult(requestCode,resultCode,data);
}
/**
*选择图片后,获取图片的路径
*@paramrequestCode
*@paramdata
*/
privatevoiddoPhoto(intrequestCode,Intentdata)
{
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};
Cursorcursor=managedQuery(photoUri,pojo,null,null,null);
if(cursor!=null)
{
intcolumnIndex=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.上传工具类,主要实现了图片的上传,上传过程的初始化监听和上传完成的监听,还有上传耗时的计算
packagecom.spring.sky.image.upload.network;
importjava.io.DataOutputStream;
importjava.io.File;
importjava.io.FileInputStream;
importjava.io.IOException;
importjava.io.InputStream;
importjava.net.HttpURLConnection;
importjava.net.MalformedURLException;
importjava.net.URL;
importjava.util.Iterator;
importjava.util.Map;
importjava.util.UUID;
importandroid.util.Log;
/**
*
*上传工具类
*@authorspringsky<br>
*Email:vipa1888@163.com<br>
*QQ:840950105<br>
*支持上传文件和参数
*/
publicclassUploadUtil{
privatestaticUploadUtiluploadUtil;
privatestaticfinalStringBOUNDARY=UUID.randomUUID().toString();//边界标识随机生成
privatestaticfinalStringPREFIX="--";
privatestaticfinalStringLINE_END="\r\n";
privatestaticfinalStringCONTENT_TYPE="multipart/form-data";//内容类型
privateUploadUtil(){
}
/**
*单例模式获取上传工具类
*@return
*/
publicstaticUploadUtilgetInstance(){
if(null==uploadUtil){
uploadUtil=newUploadUtil();
}
returnuploadUtil;
}
privatestaticfinalStringTAG="UploadUtil";
privateintreadTimeOut=10*1000;//读取超时
privateintconnectTimeout=10*1000;//超时时间
/***
*请求使用多长时间
*/
privatestaticintrequestTime=0;
privatestaticfinalStringCHARSET="utf-8";//设置编码
/***
*上传成功
*/
publicstaticfinalintUPLOAD_SUCCESS_CODE=1;
/**
*文件不存在
*/
publicstaticfinalintUPLOAD_FILE_NOT_EXISTS_CODE=2;
/**
*服务器出错
*/
publicstaticfinalintUPLOAD_SERVER_ERROR_CODE=3;
protectedstaticfinalintWHAT_TO_UPLOAD=1;
protectedstaticfinalintWHAT_UPLOAD_DONE=2;
/**
*android上传文件到服务器
*
*@paramfilePath
*需要上传的文件的路径
*@paramfileKey
*在网页上<inputtype=filename=xxx/>xxx就是这里的fileKey
*@paramRequestURL
*请求的URL
*/
publicvoiduploadFile(StringfilePath,StringfileKey,StringRequestURL,
Map<String,String>param){
if(filePath==null){
sendMessage(UPLOAD_FILE_NOT_EXISTS_CODE,"文件不存在");
return;
}
try{
Filefile=newFile(filePath);
uploadFile(file,fileKey,RequestURL,param);
}catch(Exceptione){
sendMessage(UPLOAD_FILE_NOT_EXISTS_CODE,"文件不存在");
e.printStackTrace();
return;
}
}
/**
*android上传文件到服务器
*
*@paramfile
*需要上传的文件
*@paramfileKey
*在网页上<inputtype=filename=xxx/>xxx就是这里的fileKey
*@paramRequestURL
*请求的URL
*/
publicvoiduploadFile(finalFilefile,finalStringfileKey,
finalStringRequestURL,finalMap<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);
newThread(newRunnable(){//开启线程上传文件
@Override
publicvoidrun(){
toUploadFile(file,fileKey,RequestURL,param);
}
}).start();
}
privatevoidtoUploadFile(Filefile,StringfileKey,StringRequestURL,
Map<String,String>param){
Stringresult=null;
requestTime=0;
longrequestTime=System.currentTimeMillis();
longresponseTime=0;
try{
URLurl=newURL(RequestURL);
HttpURLConnectionconn=(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;MSIE6.0;WindowsNT5.1;SV1)");
conn.setRequestProperty("Content-Type",CONTENT_TYPE+";boundary="+BOUNDARY);
//conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
/**
*当文件不为空,把文件包装并且上传
*/
DataOutputStreamdos=newDataOutputStream(conn.getOutputStream());
StringBuffersb=null;
Stringparams="";
/***
*以下是用于上传参数
*/
if(param!=null&¶m.size()>0){
Iterator<String>it=param.keySet().iterator();
while(it.hasNext()){
sb=null;
sb=newStringBuffer();
Stringkey=it.next();
Stringvalue=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=newStringBuffer();
/**
*这里重点注意: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());
/**上传文件*/
InputStreamis=newFileInputStream(file);
onUploadProcessListener.initUpload((int)file.length());
byte[]bytes=newbyte[1024];
intlen=0;
intcurLen=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=成功当响应成功,获取响应的流
*/
intres=conn.getResponseCode();
responseTime=System.currentTimeMillis();
this.requestTime=(int)((responseTime-requestTime)/1000);
Log.e(TAG,"responsecode:"+res);
if(res==200){
Log.e(TAG,"requestsuccess");
InputStreaminput=conn.getInputStream();
StringBuffersb1=newStringBuffer();
intss;
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,"requesterror");
sendMessage(UPLOAD_SERVER_ERROR_CODE,"上传失败:code="+res);
return;
}
}catch(MalformedURLExceptione){
sendMessage(UPLOAD_SERVER_ERROR_CODE,"上传失败:error="+e.getMessage());
e.printStackTrace();
return;
}catch(IOExceptione){
sendMessage(UPLOAD_SERVER_ERROR_CODE,"上传失败:error="+e.getMessage());
e.printStackTrace();
return;
}
}
/**
*发送上传结果
*@paramresponseCode
*@paramresponseMessage
*/
privatevoidsendMessage(intresponseCode,StringresponseMessage)
{
onUploadProcessListener.onUploadDone(responseCode,responseMessage);
}
/**
*下面是一个自定义的回调函数,用到回调上传文件是否完成
*
*@authorshimingzheng
*
*/
publicstaticinterfaceOnUploadProcessListener{
/**
*上传响应
*@paramresponseCode
*@parammessage
*/
voidonUploadDone(intresponseCode,Stringmessage);
/**
*上传中
*@paramuploadSize
*/
voidonUploadProcess(intuploadSize);
/**
*准备上传
*@paramfileSize
*/
voidinitUpload(intfileSize);
}
privateOnUploadProcessListeneronUploadProcessListener;
publicvoidsetOnUploadProcessListener(
OnUploadProcessListeneronUploadProcessListener){
this.onUploadProcessListener=onUploadProcessListener;
}
publicintgetReadTimeOut(){
returnreadTimeOut;
}
publicvoidsetReadTimeOut(intreadTimeOut){
this.readTimeOut=readTimeOut;
}
publicintgetConnectTimeout(){
returnconnectTimeout;
}
publicvoidsetConnectTimeout(intconnectTimeout){
this.connectTimeout=connectTimeout;
}
/**
*获取上传使用的时间
*@return
*/
publicstaticintgetRequestTime(){
returnrequestTime;
}
publicstaticinterfaceuploadProcessListener{
}
}
以上代码,我就不详细讲解原理,相关难点注释已经写得很清楚了!分享出来,和大家一起学习!
相关服务器端代码和客户端下载:
android客户端下载
javaEE服务器端
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。