http://blog.csdn.net/vipa1888/article/details/8213898
最近要搞一个项目,需要上传相册和拍照的图片,不负所望,终于完成了! 不过需要说明一下,其实网上很多教程拍照的图片,都是缩略图不是很清晰,所以需要在调用照相机的时候,事先生成一个地址,用于标识拍照的图片uri
具体上传代码:
1.选择图片和上传界面,包括上传完成和异常的回调监听
[java] view
plaincopy
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 :[email protected]<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);
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();
}
default:
}
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);
* 上传服务器响应回调
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);
case upload_in_process:
progressbar.setprogress(msg.arg1);
case upload_file_done:
string result = "响应码:"+msg.arg1+"\n响应信息:"+msg.obj+"\n耗时:"+uploadutil.getrequesttime()+"秒";
uploadimageresult.settext(result);
default:
super.handlemessage(msg);
};
public void onuploadprocess(int uploadsize) {
msg.what = upload_in_process;
msg.arg1 = uploadsize;
handler.sendmessage(msg );
public void initupload(int filesize) {
msg.what = upload_init_process;
msg.arg1 = filesize;
}
2.选择图片界面,主要涉及两种方式:选择图片和及时拍照图片
import android.content.contentvalues;
import android.database.cursor;
import android.net.uri;
import android.os.environment;
import android.provider.mediastore;
import android.view.motionevent;
import android.widget.linearlayout;
* @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;
protected void oncreate(bundle savedinstancestate) {
setcontentview(r.layout.select_pic_layout);
* 初始化加载view
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();
case r.id.dialog_layout:
finish();
case r.id.btn_take_photo:
takephoto();
case r.id.btn_pick_photo:
pickphoto();
* 拍照获取图片
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);
public boolean ontouchevent(motionevent event) {
finish();
return super.ontouchevent(event);
if(resultcode == activity.result_ok)
dophoto(requestcode,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 )
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);
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.uuid;
*
* 上传工具类
* 支持上传文件和参数
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) {
e.printstacktrace();
* @param file
* 需要上传的文件
public void uploadfile(final file file, final string filekey,
final string requesturl, final map<string, string> param) {
if (file == null || (!file.exists())) {
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,
string result = null;
requesttime= 0;
long requesttime = system.currenttimemillis();
long responsetime = 0;
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();
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);
} else {
log.e(tag, "request error");
sendmessage(upload_server_error_code,"上传失败:code=" + res);
} catch (malformedurlexception e) {
sendmessage(upload_server_error_code,"上传失败:error=" + e.getmessage());
} catch (ioexception e) {
* 发送上传结果
* @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;
* 获取上传使用的时间
public static int getrequesttime() {
return requesttime;
public static interface uploadprocesslistener{
本文章欢迎转载,但是请保留原连接地址:http://blog.csdn.net/vipa1888/article/details/8213898
以上代码,我就不详细讲解原理,相关难点注释已经写得很清楚了!分享出来,和大家一起学习!
相关服务器端代码和客户端下载:
android客户端下载
javaee服务器端
本人修改过的:
http://download.csdn.net/detail/jdsjlzx/5103005