Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android上傳圖片(及普通參數)到服務器(j2ee後台服務器,ssh框架)

android上傳圖片(及普通參數)到服務器(j2ee後台服務器,ssh框架)

編輯:關於Android編程

最近項目中需要客戶端往服務器傳輸圖片,並且還需要附帶一些普通參數,研究了幾天,把結果記錄下。

首先客戶端可服務端進行通信一般都是有http請求來發送和接收數據,這裡android中有兩種HttpClient和HttpURLConnection,這兩個都可以和後台服務器進行網絡通信,但是如何選擇哪個來進行文件傳輸呢?
谷歌官方是提倡我們使用HttpURLConnection來和服務器進行通信(這個是在android.jar中就有),HttpClient這個是org.apache.http.client.HttpClient下的一個工具類,根據網上的一些測試,得出的一些理論結果是使用HttpURLConnection來傳輸文件比HttpClient要快一些,在普通參數傳輸上都差不多。
既然谷歌推薦,所以我麼這裡就選擇HttpURLConnection來實現傳輸文件。

android客戶端

效果圖非常簡單
這裡寫圖片描述
Android客戶端邏輯:
1: 點擊選圖片—>打開系統的相冊選擇;
2:點擊上傳圖片,把圖片上傳到服務器,然後顯示進度,以及上傳完成後顯示服務器返回的json數據。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCgk8cD7K18/Iv7S/tM/uxL+1xL3hubk8YnIgLz4NCgk8aW1nIGFsdD0="這裡寫圖片描述" src="/uploadfile/Collfiles/20150421/2015042108403722.png" title="\" />
- 顯示的界面在MainAcvtitvity中;
- ConfigParamters是http請求的公共參數配置;
- HttpUrlConn是http請求主要類;
- Uploadllinsener用來監聽文件上傳的進度,以及上傳的狀態(成功,失敗,進度)。

這裡主要是看看HttpUrlConn請求類:

public class HttpUrlConn {
    //標簽
    private String TAG=HttpUrlConn;
    //HttpURLConnection請求
    private HttpURLConnection myhttpconnect;
    //結束點
    private String end = 
;
    //分割標記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 paramString,
            HashMap paramFiles,
                        ConfigParamters config){
        try {
            //這裡可以放普通參數,(第一種方法)
//          StringBuffer sb=new StringBuffer(path);
//          if(null!=paramString&¶mString.size()>0){
//              sb.append(?);
//              for(Entry 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&¶mString.size()>0){
                writeStringParam(ds, paramString);
            }
             /*把文件參數寫到服務器*/
            if(null!=paramFiles&¶mFiles.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 params){
        try{
            Set keySet = params.keySet();
            for (Iterator 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 params){
        try{
            Set keySet = params.keySet();
            getFilesSize(params);
            for (Iterator 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 params){
        for(Entry 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這個方法主要是為了傳輸普通的參數;
- 把普通參數裝入HashMap中然後循環寫出數據,這裡的數據是需要拼接的,因為我們提交數據是模擬from表單提交。
4:writeFileParam(DataOutputStream,HashMap這個方法只要是用來傳輸文件參數;
- 把需要傳輸的文件都裝在HashMap中,循環遍歷hashmap中的文件,一一寫到服務器。(在這個方法中獲取了所有文件的總大小,用於計算當前的傳輸進度,還有這裡的name和服務器的要一樣。)
5:getFilesSize(HashMap獲取文件的總大小;
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表單提交上來的普通參數如果是中文這裡好像還是會亂碼。
 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved