当前位置: 代码迷 >> Android >> android上传图片(及普普通通参数)到服务器(j2ee后台服务器,ssh框架)
  详细解决方案

android上传图片(及普普通通参数)到服务器(j2ee后台服务器,ssh框架)

热度:28   发布时间:2016-04-28 01:22:22.0
android上传图片(及普通参数)到服务器(j2ee后台服务器,ssh框架)

最近项目中需要客户端往服务器传输图片,并且还需要附带一些普通参数,研究了几天,把结果记录下。

首先客户端可服务端进行通信一般都是有http请求来发送和接收数据,这里android中有两种HttpClient和HttpURLConnection,这两个都可以和后台服务器进行网络通信,但是如何选择哪个来进行文件传输呢?
谷歌官方是提倡我们使用HttpURLConnection来和服务器进行通信(这个是在android.jar中就有),HttpClient这个是org.apache.http.client.HttpClient下的一个工具类,根据网上的一些测试,得出的一些理论结果是使用HttpURLConnection来传输文件比HttpClient要快一些,在普通参数传输上都差不多。
既然谷歌推荐,所以我么这里就选择HttpURLConnection来实现传输文件。

android客户端

效果图非常简单
这里写图片描述
Android客户端逻辑:
1: 点击选图片—>打开系统的相册选择;
2:点击上传图片,把图片上传到服务器,然后显示进度,以及上传完成后显示服务器返回的json数据。

首先看看项目的结构
这里写图片描述
- 显示的界面在MainAcvtitvity中;
- ConfigParamters是http请求的公共参数配置;
- HttpUrlConn是http请求主要类;
- Uploadllinsener用来监听文件上传的进度,以及上传的状态(成功,失败,进度)。

这里主要是看看HttpUrlConn请求类:

public class HttpUrlConn {    //标签    private String TAG="HttpUrlConn";    //HttpURLConnection请求    private HttpURLConnection myhttpconnect;    //结束点    private String end = "\r\n";    //分割标记twoHyphens    private String twoHyphens = "--";    //分割标记    private String boundary = "*****";    //数据输出管道    private DataOutputStream ds=null;    //文件上传监听    private UploadLinsener uploadlinsener;    //文件总大小    private double allFilesize=0;    //当前传输了多少    private double curr_ret=0;    /**     * HttpURLConnection连接服务器请求     * @param path :接口地址     * @param param1 :普通参数     * @param paramFiles:需要上传的文件参数     * @param config:连接公共属性配置     * @return     */public  HttpURLConnection getHttpUrlConnInstances(String path,        HashMap<String, String> paramString,            HashMap<String, File> paramFiles,                        ConfigParamters config){        try {            //这里可以放普通参数,(第一种方法)//          StringBuffer sb=new StringBuffer(path);//          if(null!=paramString&&paramString.size()>0){//              sb.append("?");//              for(Entry<String, String> data:paramString.entrySet()){ //                  sb.append(data.getKey()+"="+data.getValue());//                  sb.append("&");//              }//          }   //      path=sb.substring(0, sb.lastIndexOf("&"));        URL url=new URL(path);              myhttpconnect=(HttpURLConnection)                                url.openConnection();        /* 允许Input、Output,post中不使用Cache */        myhttpconnect.setDoInput(config.isDoInput());        myhttpconnect.setDoOutput(config.isDoOutput());        myhttpconnect.setUseCaches(config.isUseCaches());        /* 设置传送的method=POST */          myhttpconnect.              setRequestMethod(config.getUseMethod());        /*设置属性 setRequestProperty */                myhttpconnect       .setRequestProperty("Connection", "Keep-Alive");            myhttpconnect.setRequestProperty("Charset", "UTF-8");            myhttpconnect.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);            /* 设置DataOutputStream */            ds = new DataOutputStream(                        myhttpconnect.getOutputStream());            /*把普通参数写到服务器*/            if(null!=paramString&&paramString.size()>0){                writeStringParam(ds, paramString);            }             /*把文件参数写到服务器*/            if(null!=paramFiles&&paramFiles.size()>0){                writeFileParam(ds, paramFiles);            }            //添加结尾标志            paramsEnd(ds);        if(myhttpconnect.getResponseCode()                    ==HttpURLConnection.HTTP_OK){             InputStream is =                      myhttpconnect.getInputStream();            String successMsg=InputStremtoString(is);            //成功            if(uploadlinsener!=null){               uploadlinsener.uploadSucsess(successMsg);            }        }else{              uploadlinsener.uploadFail("错误,错误码                    ResponseCode:"+                      myhttpconnect.getResponseCode());            }            ds.close();        } catch (MalformedURLException e) {            // TODO Auto-generated catch block            e.printStackTrace();            if(uploadlinsener!=null){                uploadlinsener.uploadFail(e.toString());            }        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();            if(uploadlinsener!=null){                uploadlinsener.uploadFail(e.toString());            }        } catch (Exception e) {            // TODO Auto-generated catch block            e.printStackTrace();            if(uploadlinsener!=null){                uploadlinsener.uploadFail(e.toString());            }        }        return myhttpconnect;    }/*** 把字节输入流转换成字符串* @return*/private String InputStremtoString(InputStream is)throws Exception{        int ch;        StringBuffer b = new StringBuffer();        byte[] bt=new byte[1024];        while ((ch = is.read(bt)) != -1)        {               b.append(new String(bt, 0, ch, "UTF-8"));        }        return b.toString();    }/*** 传普通参数(第二种方法)* @param parm:参数*/private void writeStringParam(DataOutputStream ds,                    HashMap<String, String> params){        try{            Set<String> keySet = params.keySet();            for (Iterator<String> it =keySet.iterator();                                             it.hasNext();){                String name = it.next();                String value = params.get(name);                ds.writeBytes(twoHyphens + boundary + end);                ds.writeBytes("Content-Disposition: form-data; name=\"" + name +"\""+ end);                ds.writeBytes(end);                //URLEncoder.encode(value)                ds.writeBytes(new String(value.getBytes(),"UTF-8")+ end);            }        }catch(Exception e){            e.printStackTrace();        }    }/**** 传输文件* @param ds :数据传输通道* @param params :参数*/private void writeFileParam(DataOutputStream ds,HashMap<String, File> params){        try{            Set<String> keySet = params.keySet();            getFilesSize(params);            for (Iterator<String> it =keySet.iterator();                                             it.hasNext();){                String name = it.next();                File value = params.get(name);                ds.writeBytes(twoHyphens + boundary + end);                 ds.writeBytes("Content-Disposition: form-data; name=\"" + name + "\"; filename=\"" + URLEncoder.encode(value.getName()) + "\""+end);                ds.writeBytes("Content-Type: " + getContentType(value) + end);                ds.writeBytes(end);                ds.write(getBytes(value));                ds.writeBytes(end);            }        }catch(Exception e){            e.printStackTrace();        }    }/*** 获取要传输文件总共大小* @param params*/private void getFilesSize(HashMap<String, File> params){        for(Entry<String, File> data:params.entrySet()){            File f=data.getValue();            allFilesize+=f.length();        }        Log.i(TAG, "AllFileSize:"+allFilesize);    }/*** 获取文件的上传类型,图片格式为image/png,image/jpg等。非图片为application/octet-stream * @param f 文件 * @return * @throws Exception*/private String getContentType(File f) throws Exception{        return "application/octet-stream";}/*** 添加结尾数据  * @param ds:数据传输通道*  * @throws Exception*/private void paramsEnd( DataOutputStream ds) throws Exception {         ds.writeBytes(twoHyphens + boundary +                                 twoHyphens + end);          ds.writeBytes(end);           }     /**     * 把文件转换成字节数组     * @param f:文件     * @return     * @throws Exception     */private byte[] getBytes(File f) throws Exception{    FileInputStream in = new FileInputStream(f);    ByteArrayOutputStream out = new ByteArrayOutputStream();        byte[] b = new byte[1024];        int n;        while ((n = in.read(b)) != -1)        {            out.write(b, 0, n);            if(allFilesize>0){                curr_ret+=n;                double level=(curr_ret/allFilesize)*100;                Log.i("result", ""+level);                if(uploadlinsener!=null){                    uploadlinsener.uploading(level);                }            }        }        in.close();       return out.toByteArray();    }public void setUploadlinsener(UploadLinsener uploadlinsener) {        this.uploadlinsener = uploadlinsener;    }}

上面的代码是HttpUrlConn的全部代码。
1: getHttpUrlConnInstances()获取并且请求连接服务器;
-方法中主要是获取连接,并且配置连接,然后拼接参数,发送到服务器,然后通过myhttpconnect.getInputStream()获取到服务器返回的数据。
2:InputStremtoString(InputStream)把字节流转换成String;
- 这里主要是为了处理服务器返回的数据。(这里注意编码)
3:writeStringParam(DataOutputStream,HashMap<String, String>)这个方法主要是为了传输普通的参数;
- 把普通参数装入HashMap<String, String>中然后循环写出数据,这里的数据是需要拼接的,因为我们提交数据是模拟from表单提交。
4:writeFileParam(DataOutputStream,HashMap<String, File>)这个方法只要是用来传输文件参数;
- 把需要传输的文件都装在HashMap<String, File>中,循环遍历hashmap中的文件,一一写到服务器。(在这个方法中获取了所有文件的总大小,用于计算当前的传输进度,还有这里的name和服务器的要一样。)
5:getFilesSize(HashMap<String, File>)获取文件的总大小;
6:getContentType(File f)获取文件的上传类型,图片格式为image/png,image/jpg等。非图片为application/octet-stream;
7:paramsEnd(DataOutputStream)添加结尾数据;
8:getBytes(File) 把文件转换成字节数组;
9:setUploadlinsener(UploadLinsener)设置传输监听;


J2ee服务端(ssh搭建的环境)

这里我们使用struts2的一个组件来实现配合客户端文件上传。
这里写图片描述
用struts,spring,hibernate三大框架搭建好的项目,这里项目搭建过程就不演示了。
这里的核心代码在FileUploadAction中:

public class FileUploadAction extends ActionSupport{    public String phoneinfo="NXJ570";    public void uploadfielandparam() throws Exception{        System.out.println("upload");        HttpServletRequest request=            ServletActionContext.getRequest();        System.out.println(request.getContentType());       System.out.println(request.getCharacterEncoding());        System.out.println(request.getContentLength());         //临时文件夹,在tomcat项目下的temp        String temp = ServletActionContext                       .getServletContext()                          .getRealPath("")+ "\\temp";        System.out.println(temp);        //上传文件存放地方        String basepath=ServletActionContext                        .getServletContext()                            .getRealPath("")+"\\myfile";        //获取Response        HttpServletResponse resp=                ServletActionContext.getResponse();        DiskFileItemFactory factory =                         new DiskFileItemFactory();        //单个文件缓存最大值        factory.setSizeThreshold(10 * 1024 * 1024);        // 缓冲区        factory.setRepository(new File(temp));        //文件上传组件(关键)        ServletFileUpload upload1=                new ServletFileUpload(factory);        upload1.setFileSizeMax(10000000);        upload1.setSizeMax(480000000);        upload1.setHeaderEncoding("UTF-8");         // 设置一旦文件大小超过getSizeThreshold()        //的值时数据存放在硬盘的目录        // 开始读取上传信息        int index = 0;        List fileItems= null;        try        {            fileItems=upload1.parseRequest(request);            System.out.println("list=" + fileItems);        }        catch (Exception e)        {            e.printStackTrace();        }        Iterator iter = fileItems.iterator();        // 依次处理每个上传的文件        while (iter.hasNext())        {            FileItem item = (FileItem) iter.next();            // 忽略其他不是文件域的所有表单信息            if (!item.isFormField())            {                String name = item.getName();                // 获取上传文件名,包括路径                name = name.substring(                            name.lastIndexOf("\\") + 1);                // 从全路径中提取文件名                long size = item.getSize();                if ((name == null                     || name.equals("")) && size == 0)                continue;                int point = name.indexOf(".");                name = (new Date()).getTime()                        + name.substring(point, name.length());                System.out.println("fileName="+name);                index++;                File fNew = new File(basepath, name);                try                {                    item.write(fNew);                }                catch (Exception e)                {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }            else            // 取出不是文件域的所有表单信息            {                //如果包含中文应写为:(转为UTF-8编码)                String key=item.getFieldName();                String fieldvalue =                        .getBytes(),"UTF-8");//UTF-8                    System.out                           .println("                            params:"+key+"="+fieldvalue);            }        }        //把对象转换成json        Gson gson = new Gson();        myobj obj1=new myobj("0", "seccessed",                                     "服务器已经接收到文件");        String json = gson.toJson(obj1);        System.out.println(json);        //设置格式(必须设置,否则客户端接收到的json中文乱码)        resp.setContentType("text/html; charset=utf-8");        PrintWriter out = resp.getWriter();        out.println(json);        out.flush();    }    //实体对象    class myobj{        private String retcode;        private String retmessage;        private String retdata;        public myobj(String retcode,                 String retmessage, String retdata) {            super();            this.retcode = retcode;            this.retmessage = retmessage;            this.retdata = retdata;        }        public String getRetcode() {            return retcode;        }        public void setRetcode(String retcode) {            this.retcode = retcode;        }        public String getRetmessage() {            return retmessage;        }        public void setRetmessage(String retmessage) {            this.retmessage = retmessage;        }        public String getRetdata() {            return retdata;        }        public void setRetdata(String retdata) {            this.retdata = retdata;        }       }

这个类是核心业务类,当客户端发送请求是进入到这个方法中,并且获取到参数数据。
在服务端有两种方式能后获取到android的普通参数,
一是通过HttpServletRequest的getParameter(arg0)方法来获取;
二是从提交的表单中获取:

    //获取key    String key=item.getFieldName();    //获取vaule    String fieldvalue =new             String(item.getString().getBytes(),"UTF-8");

经过测试传输速度的确挺快的5MB的图片几秒钟就能传输完成,注意这里如果是在android客户端模拟机中调试程序,那里的请求地址中的ip应该为10.0.0.2:8080…..否则找不到服务器,如果是真机上测试可以直接发布到你电脑的tomcat中,然后把ip改成你点击的ip就可以了(这里电脑和android手机需要连接到同一个网络wifi,也就是内网,当然也可以拿到公司的服务器上测试)。
项目测试通过,效果也挺好的,不过这里还有一个问题没解决,就是通过from表单提交上来的普通参数如果是中文这里好像还是会乱码。
项目地址:http://download.csdn.net/detail/leifengpeng/8614101

  相关解决方案