• 微软原版系统

  • 一键重装系统

  • 纯净系统

  • 在线技术客服

魔法猪系统重装大师 一键在线制作启动 U 盘 PE 系统 用一键重装的魔法拯救失去灵魂的系统
当前位置:首页 > 教程 > 电脑教程

利用WCF与Android实现图片上传并传递参数

时间:2015年04月02日 15:20:10    来源:魔法猪系统重装大师官网    人气:9628
前往cf活动专题

最近做一个项目后端使用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(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"?>

  
    
  
  
    
  
  
    
      
        
          
        
      
      
        
          
          
          
          
          
        
      
    

    
      
        
          
          
        
      
    
    
      
         
      
    
  

此处有些要注意的地方:

(1):此处采用的是webHttpBinding 所以一定要设置behaviorConfiguration才会有效果,其中helpEnabled="true"则是为实现可以在发布可以查看帮助信息    

        
          
        

(2):为了实现上传大文件所以我们要如下设置最大值,其中security是设置访问服务的认证,此处是把它设置成为不认证

      
        
          
          
        
      

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,"上传失败:code=" + 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            bLoop = bRefArr[i];
            iOutcome+= (bLoop & 0xFF) << (8 * i);
         }
        return iOutcome;
     }
}

五:运行效果:

利用,WCF,与,Android,实现,图片,上传,并,传递
栏目:电脑教程 阅读:1000 2023/12/27
Win7教程 更多>>
U盘教程 更多>>
Win10教程 更多>>
魔法猪学院 更多>>

Copyright © 2015-2023 魔法猪 魔法猪系统重装大师

本站发布的系统仅为个人学习测试使用,请在下载后24小时内删除,不得用于任何商业用途,否则后果自负,请支持购买微软正版软件。

在线客服 查看微信 返回顶部