• <td id="ae6ms"><li id="ae6ms"></li></td>
  • <xmp id="ae6ms"><td id="ae6ms"></td><table id="ae6ms"></table>
  • <table id="ae6ms"></table>
  • <td id="ae6ms"></td>
    <td id="ae6ms"></td>
  • <table id="ae6ms"></table><table id="ae6ms"><td id="ae6ms"></td></table>
  • <td id="ae6ms"></td>
  • <table id="ae6ms"><li id="ae6ms"></li></table>
  • <table id="ae6ms"></table>
    西西軟件園多重安全檢測下載網站、值得信賴的軟件下載站!
    軟件
    軟件
    文章
    搜索

    首頁編程開發Android → 利用WCF與Android實現圖片上傳并傳遞參數

    利用WCF與Android實現圖片上傳并傳遞參數

    前往專題相關軟件相關文章發表評論 來源:西西整理時間:2013/9/2 23:23:17字體大?。?em class="fontsize">A-A+

    作者:西西點擊:217次評論:1次標簽: WCF Android

    • 類型:源碼相關大?。?i>79KB語言:中文 評分:5.0
    • 標簽:
    立即下載

    最近做一個項目后端使用WCF接收Android手機拍照并帶其它參數保存到服務器里;剛好把最近學習的WCF利用上,本以為是個比較簡單的功能應該很好實現,沒想到其中碰到不少問題,在網上搜索很久一直沒有想到的解決方案,最后實現對數據流的分段寫入然后后端再來解析流實現的此功能;后端運用WCF中的REST來接收數據;REST還是比較簡單的知識,若是不懂可以簡單網上了解一下;下面我們先了解一些本次運用到的理論知識:

    一:理論知識

    由于低層協議特性限制,WCF的流模式只支持如下四種:1:BasicHttpBinding 2:NetTcpBinding 3:NetNamedPipeBinding 4:WebHttpBinding

    1.設置TransferMode。它支持四種模式(Buffered、Streamed、StreamedRequest、StreamedResponse),請根據具體情況設置成三種Stream模式之一。

    2.修改MaxReceivedMessageSize。該值默認大小為64k,因此,當傳輸數據大于64k時,則拋出CommunicationException異常。  

    3.修改receiveTimeout 和sendTimeout。大數據傳送時間較長,需要修改這兩個值,以免傳輸超時。

    二:解決問題

    WCF如果使用Stream做為參數時只能唯一一個,不能有其它另外的參數,這個也是本次碰到要重點解決的一個問題;可是我們Android手機除的圖片還要有其它的參數,最后決定采用手機端把參數跟圖片都一起寫入Stream里面,后端WCF再來解析這個參數的流;

    下面就是定義好Stream的格式,傳過來的Stream分成三部分: 參數信息長度  參數信息   圖片

    1 參數信息長度(1字節):用于存放參數信息的長度(以字節為單位);

    2 參數信息: 除圖片以外的參數,以JSON的形式存放如{"type":"jpg","EmployeeID":"12","TaskID":"13"}

    3 圖片:圖片的字節

    三:WCF編碼內容

    1:我們首先定義一個WCF契約,由于我們運用REST(在命名空間ServiceModel.Web下面)契約IAndroidInfo內容如下,采用POST方式進行接收:

    using System.ServiceModel;
    using System.Runtime.Serialization;
    using System.ServiceModel.Web;
    using System.IO;
    
    namespace Coreius.CEIMS.AndroidInterface
    {
        [ServiceContract]
        public interface IAndroidInfo
        {
             [WebInvoke(UriTemplate = "GpsUpFile", Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json, 
    ResponseFormat = WebMessageFormat.Json)]
            bool GpsUpFile(Stream ImageContext);
        }
    }

    2:根據契約我們定義服務的內容,接收一個流的參數內容,首先把這個Stream轉化成字節,然后根據我們先前約定好的內容獲得第一個字節的值,再根據此值定義我們另外三個參數的字節長度,再通過JSON轉換格式把它里面的三個參數值取出來,最后其它字節是存放一張手機拍的照片,把它存放在于們服務器D盤文件夾下

    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    using System.ServiceModel.Web;
    using System.IO;
    using Newtonsoft.Json;
    
    namespace Coreius.CEIMS.AndroidService
    {
        public class AndroidInfoService:IAndroidInfo
        {
    
          public bool GpsUpFile(Stream ImageContext)
            {
                byte[] m_Bytes = ReadToEnd(ImageContext);
                int len = (int)m_Bytes[0];
    
                byte[] data = m_Bytes.Skip(1).Take(len).ToArray();
                string Jsonstr = System.Text.Encoding.Default.GetString(data);
    
                JsonModel item = JsonConvert.DeserializeObject<JsonModel>(Jsonstr);
                string ImageType=item.type;
                string EmployeeID=item.EmployeeID;
                string TaskID=item.TaskID;
    
                byte[] Imagedata = m_Bytes.Skip(1 + len).ToArray();
    
                string DiskName = "d:";
                string FileAddress = "\\UpLoad\\";
                string LocationAddress = DiskName + FileAddress;
                if (!DirFileHelper.IsExistDirectory(LocationAddress))
                {
                    DirFileHelper.CreateDirectory(LocationAddress);
                }
    
                string ImageName = DateTime.Now.ToString("yyyyMMddhhmmss.") + ImageType;
                string ImagePath = LocationAddress + ImageName;
                if (!File.Exists(ImagePath))
                {
                    try
                    {
                        System.IO.File.WriteAllBytes(ImagePath, Imagedata);
                        ImageContext.Close();
                        return true;
                    }
                    catch
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }
        }
    }

    上面的代碼用到幾個方法,比如把流轉化成字節、把JSON轉化成實現等,代碼如下:

    public byte[] ReadToEnd(System.IO.Stream stream)
            {
                long originalPosition = 0;
    
                if (stream.CanSeek)
                {
                    originalPosition = stream.Position;
                    stream.Position = 0;
                }
    
                try
                {
                    byte[] readBuffer = new byte[4096];
    
                    int totalBytesRead = 0;
                    int bytesRead;
    
                    while ((bytesRead = stream.Read(readBuffer, totalBytesRead, readBuffer.Length - totalBytesRead)) > 0)
                    {
                        totalBytesRead += bytesRead;
    
                        if (totalBytesRead == readBuffer.Length)
                        {
                            int nextByte = stream.ReadByte();
                            if (nextByte != -1)
                            {
                                byte[] temp = new byte[readBuffer.Length * 2];
                                Buffer.BlockCopy(readBuffer, 0, temp, 0, readBuffer.Length);
                                Buffer.SetByte(temp, totalBytesRead, (byte)nextByte);
                                readBuffer = temp;
                                totalBytesRead++;
                            }
                        }
                    }
    
                    byte[] buffer = readBuffer;
                    if (readBuffer.Length != totalBytesRead)
                    {
                        buffer = new byte[totalBytesRead];
                        Buffer.BlockCopy(readBuffer, 0, buffer, 0, totalBytesRead);
                    }
                    return buffer;
                }
                finally
                {
                    if (stream.CanSeek)
                    {
                        stream.Position = originalPosition;
                    }
                }
            }
    
    
    
        public class JsonModel
        {
            public string type { get; set; }
            public string EmployeeID { get; set; }
            public string TaskID { get; set; }
        }

    3:新建一個文本,然后修改其后綴名為.svc,作為我們發布服務(宿主為IIS)讓Android手機調用, 然后把下面的代碼寫入

    <%@ ServiceHost Language="C#" Debug="true" Service="Coreius.CEIMS.AndroidService.AndroidInfoService" %>

    修改Web.config里面的內容:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <appSettings>
        <add key="ConnectionString" value="server=127.0.0.1;database=Coreius;uid=sa;pwd=admin"/>
      </appSettings>
      <system.web>
        <compilation debug="true" targetFramework="4.0" />
      </system.web>
      <system.serviceModel>
        <behaviors>
          <endpointBehaviors>
            <behavior name="webHttp">
              <webHttp helpEnabled="true"/>
            </behavior>
          </endpointBehaviors>
          <serviceBehaviors>
            <behavior name="MapConfigBehavior">
              <!-- 為避免泄漏元數據信息,請在部署前將以下值設置為 false 并刪除上面的元數據終結點 -->
              <serviceMetadata httpGetEnabled="true"/>
              <!-- 要接收故障異常詳細信息以進行調試,請將以下值設置為 true。在部署前設置為 false 以避免泄漏異常信息 -->
              <serviceDebug includeExceptionDetailInFaults="true"/>
              <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
            </behavior>
          </serviceBehaviors>
        </behaviors>
    
        <bindings>
          <webHttpBinding>
            <binding name="webHttpBindConfig" receiveTimeout="00:30:00" sendTimeout="00:30:00" maxReceivedMessageSize="104857600" transferMode="Streamed">
              <readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647"/>
              <security mode="None"></security>
            </binding>
          </webHttpBinding>
        </bindings>
        <services>
          <service name="Coreius.CEIMS.AndroidService.AndroidInfoService" behaviorConfiguration="MapConfigBehavior">
            <endpoint binding="webHttpBinding" contract="Coreius.CEIMS.AndroidInterface.IAndroidInfo" bindingConfiguration="webHttpBindConfig" 
    
    behaviorConfiguration="webHttp"/> 
          </service>
        </services>
      </system.serviceModel>
    </configuration>

    此處有些要注意的地方:

    (1):此處采用的是webHttpBinding 所以一定要設置behaviorConfiguration才會有效果,其中helpEnabled="true"則是為實現可以在發布可以查看幫助信息    

            <behavior name="webHttp">
              <webHttp helpEnabled="true"/>
            </behavior>

    (2):為了實現上傳大文件所以我們要如下設置最大值,其中security是設置訪問服務的認證,此處是把它設置成為不認證

          <webHttpBinding>
            <binding name="webHttpBindConfig" receiveTimeout="00:30:00" sendTimeout="00:30:00" maxReceivedMessageSize="104857600" transferMode="Streamed">
              <readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647"/>
              <security mode="None"></security>
            </binding>
          </webHttpBinding>

    4:編寫完上面的代碼后就可以服務器IIS上部署這個WCF服務:

    四:Android編碼

    由于Android手機端的代碼是另外一個朋友編寫,所以就把大體的代碼貼出來,大體的原理就是把參數跟圖片寫入流,然后調用部署好的WCF服務

    代碼一:因為服務器不是公用的,所以下面的IP我就隨便修改的一個;

    private void toUploadFile(File file) throws FileNotFoundException {
            String result = null;
            requestTime= 0;
            int res = 0;
            long requestTime = System.currentTimeMillis();
            long responseTime = 0;
            //封裝參數信息
            JSONObject jsonObject = new JSONObject();
            try {
                jsonObject.put("EmployeeID", MainActivity.guid);
                jsonObject.put("TaskID", "e52df9b4-ee3b-46c5-8387-329b76356641");
                String[] type = file.getName().split("\\.");
                jsonObject.put("type", type[type.length-1]);
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            /**上傳文件*/
            HttpParams httpParameters = new BasicHttpParams();
            HttpConnectionParams.setConnectionTimeout(httpParameters, 1000*30);
            HttpConnectionParams.setSoTimeout(httpParameters, 1000*30);
            HttpConnectionParams.setTcpNoDelay(httpParameters, true);
            String path = PictureUtil.zipNewImage(file);    //壓縮文件后返回的文件路徑
            byte[] bytes = null;
            InputStream is;
            File myfile = new File(path);
            try {
                is = new FileInputStream(path);
                bytes = new byte[(int) myfile.length()];
                int len = 0;
                int curLen = 0;
                while ((len = is.read(bytes)) != -1) {
                    curLen += len;
                    is.read(bytes);
                }
                is.close();
            } catch (FileNotFoundException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            byte[] updata = GpsImagePackage.getPacket(jsonObject.toString(), bytes);    //參數與文件封裝成單個數據包
            HttpClient httpClient = new DefaultHttpClient(httpParameters);
            HttpPost httpPost = new HttpPost(MyUrl.upload_file);
            HttpResponse httpResponse;
            //單個文件流上傳
            InputStream input = new ByteArrayInputStream( updata );
            InputStreamEntity reqEntity;
            reqEntity = new InputStreamEntity(input, -1);
            reqEntity.setContentType("binary/octet-stream");
            reqEntity.setChunked(true);
            httpPost.setEntity(reqEntity);
            try {
                httpResponse = httpClient.execute(httpPost);
                responseTime = System.currentTimeMillis();
                this.requestTime = (int) ((responseTime-requestTime)/1000);
                res = httpResponse.getStatusLine().getStatusCode();
                if (httpResponse.getStatusLine().getStatusCode() ==200) {
                    Log.e(TAG, "request success");
                    Log.e(TAG, "result : " + result);
                    return;
                } else {
                    Log.e(TAG, "request error");
                    sendMessage(UPLOAD_SERVER_ERROR_CODE,"上傳失?。篶ode=" + res);
                    return;
                }
                } catch (ClientProtocolException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
        }
    package com.anthony.util;
    /**
     * 服務器端接口
     * @author YWJ
     *
     */
    public class MyUrl {
        public static String upload_GPS = "http://122.199.19.23:8088/AndroidInfoService.svc/SetGpsInfo";
    }

    代碼二:

    package com.anthony.util;
    public class GpsImagePackage {
        public GpsImagePackage() {
            // TODO Auto-generated constructor stub
        }
        //封裝字節數組與參數
        public static byte[] getPacket(String json,byte[] image){
            byte[] jsonb = json.getBytes();
            int length = image.length + jsonb.length;
            System.out.println(image.length +"    "+ jsonb.length);
            byte[] bytes = new byte[length+1];
            byte[] lengthb = InttoByteArray(jsonb.length, 1);
            System.arraycopy(lengthb, 0, bytes, 0, 1);
            System.arraycopy(jsonb, 0, bytes, 1, jsonb.length);
            System.arraycopy(image, 0, bytes, 1+jsonb.length, image.length);
            return bytes;
        }
        //將int轉換為字節數組
        public static byte[] InttoByteArray(int iSource, int iArrayLen) {
            byte[] bLocalArr = new byte[iArrayLen];
            for ( int i = 0; (i < 4) && (i < iArrayLen); i++) {
                 bLocalArr[i] = (byte)( iSource>>8*i & 0xFF );
            }
             return bLocalArr;
        }
         // 將byte數組bRefArr轉為一個整數,字節數組的低位是整型的低字節位
         public static int BytestoInt(byte[] bRefArr) {
             int iOutcome = 0;
             byte bLoop;
             for ( int i =0; i<bRefArr.length ; i++) {
                bLoop = bRefArr[i];
                iOutcome+= (bLoop & 0xFF) << (8 * i);
             }
            return iOutcome;
         }
    }

    五:運行效果:

      相關評論

      閱讀本文后您有什么感想? 已有人給出評價!

      • 8 喜歡喜歡
      • 3 頂
      • 1 難過難過
      • 5 囧
      • 3 圍觀圍觀
      • 2 無聊無聊

      熱門評論

      最新評論

      發表評論 查看所有評論(1)

      昵稱:
      表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
      字數: 0/500 (您的評論需要經過審核才能顯示)
      女人让男人桶30分钟免费视频,女人张开腿让男人桶个爽,一进一出又大又粗爽视频
    • <td id="ae6ms"><li id="ae6ms"></li></td>
    • <xmp id="ae6ms"><td id="ae6ms"></td><table id="ae6ms"></table>
    • <table id="ae6ms"></table>
    • <td id="ae6ms"></td>
      <td id="ae6ms"></td>
    • <table id="ae6ms"></table><table id="ae6ms"><td id="ae6ms"></td></table>
    • <td id="ae6ms"></td>
    • <table id="ae6ms"><li id="ae6ms"></li></table>
    • <table id="ae6ms"></table>