天天看点

android选择图片或拍照图片上传到服务器(包括上传参数)

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