IOS调用WCF提供的服务方法,但是方法的参数是WCF那边自定义的对象,这样有办法调用么,如果可以IOS应该怎么传参呢?请问有了解的么,...

最近做一个项目后端使用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是设置访问服务的认证,此处是把它设置成为不认证,transferMode就是设置运用流的模式

      <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 blocke.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 blocke1.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.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 blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.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;}
}

 

五:运行效果:

 

 

如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】按钮。  因为,我的写作热情也离不开您的肯定支持。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/291220.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ABP vNext微服务架构详细教程——项目部署

1基础配置在之前的文章中&#xff0c;我们已经配置了Kubernetes集群并安装了管理工具Kubesphere&#xff0c;文章地址为&#xff1a;https://mp.weixin.qq.com/s/MgpdMv5A-fYxN7XY8N9Djw登录Kubesphere页面&#xff0c;打开工作台&#xff0c;在平台资源选项卡中点击“企业空间…

offsetTop和scrollTop的差别

近期想写个组件&#xff0c;结果被这两个属性搞的有点晕&#xff0c;查了下文档和资料&#xff0c;对这两个属性总结例如以下&#xff1a; 一直以来对offsetLeft&#xff0c;offsetTop&#xff0c;scrollLeft&#xff0c;scrollTop这几个方法非常迷糊&#xff0c;花了一天的时间…

quartz (一) 基于 Quartz 开发企业级任务调度应用

本文转自&#xff1a;http://www.ibm.com/developerworks/cn/opensource/os-cn-quartz/ Quartz 基本概念及原理 Quartz Scheduler 开源框架 Quartz 是 OpenSymphony 开源组织在任务调度领域的一个开源项目&#xff0c;完全基于 Java 实现。该项目于 2009 年被 Terracotta 收购&…

C# 11 中的参数 null 检查

C# 11 中的参数 null 检查IntroC# 11 将引入一个新的操作符 !! 来简化我们代码中的对于参数的 null 检查&#xff0c;昨天发布的 .NET 7 Preview 1 已经支持了这一语法&#xff0c;感兴趣的不妨来试一下吧&#xff0c;下面我们就来看一下如何使用吧Prepare如果你想在本地代码中…

cms的 php代码,KingCMS/PHP可执行代码

实例:Example :{king:title/}{king:content/}作者:{king:_author/}上面的代码没有什么特别的地方&#xff0c;但客户的要求有了变化&#xff0c;他想在详细页的内容开始前调用缩略图&#xff0c;没有则忽略。所以问题也来了&#xff0c;因为有的文章有缩略图&#xff0c;有的没…

CentOS单机安装k8s并部署.NET 6程序

学习云原生&#xff0c;k8s 是一个基础&#xff0c;为了做一些实验&#xff0c;单机部署是最方便的&#xff0c;下面将介绍在 CentOS 中单机安装 k8s &#xff0c;并将一个 .NET 6 的程序发布到 k8s 中。环境宿主机&#xff1a;Mac 10.15.7CentOS版本&#xff1a;7.6内存&#…

php session缓存,扫盲:php session缓存至memcached中的方法

memcached是一套分布式的快取系统&#xff0c;当初是DangaInteractive为了LiveJournal所发展的&#xff0c;但被许多软件(如MediaWiki)所使用。这是一套开放源代码软件&#xff0c;以BSDlicens更改为&#xff1a;session.save_handler memcachesession.save_path"tcp://12…

MASA Framework - DDD设计(2)

Clean Architecture国内对于Clean Architecture的翻译很多&#xff0c;干净/整洁/清晰。但无论哪一种都说明了它简洁、清晰的特性。早期它长这样看到这张图的同学可能会对另外一张图有印象洋葱架构(Onion)现在长这样看起来好像是亲戚&#xff0c;它们的确也有着千丝万缕的关系分…

SpringMVC核心分发器DispatcherServlet分析[附带源码分析]

目录 前言DispatcherServlet初始化过程DispatcherServlet处理请求过程总结参考资料前言 SpringMVC是目前主流的Web MVC框架之一。 如果有同学对它不熟悉&#xff0c;那么请参考它的入门blog&#xff1a;http://www.cnblogs.com/fangjian0423/p/springMVC-introduction.html 本…

WPF 展示视频修改为WriteableBitmap

WPF开发者QQ群&#xff1a;340500857由于微信群人数太多入群请添加小编微信号yanjinhuawechat 或 W_Feng_aiQ 邀请入群需备注WPF开发者 PS&#xff1a;有更好的方式欢迎推荐。接着上一篇&#xff0c;进行WriteableBitmap性能优化修改后运行对比如下&#xff1a;前&#xff08;C…

linux之类似Windows的资源管理器gnome-system-monitor(可用这个杀死进程)

1、使用 直接运行下面命令gnome-system-monitor 如果没有安装用下面命令安装sudo apt-get install gnome-system-monitor 2、结果 可以点击右键然后杀死相关进程&#xff0c;这也是杀死进程的办法。

HttpClient异常处理手册

HttpClient异常处理手册 开源中国 发表于 2014-08-26 19:44:06异常处理 HttpClient的使用者在执行HTPP方法&#xff08;GET,PUT,DELETE等&#xff09;&#xff0c;可能遇到会两种主要类型的异常&#xff1a; 传输异常协议异常并不是所有的异常都会传播给HttpClient的用户。Htt…

再读《精通css》02:选择器

2019独角兽企业重金招聘Python工程师标准>>> 1.2 为样式找到目标1、类型选择器用来选择特定类型的原素。比如p&#xff0c;a&#xff0c;h1等等。也叫元素选择器或简单选择器。2、后代选择器用来寻找特定元素或元素组的后代。后代选择器由两个选择器之间的空格表示。…

余弦欧式距离matlab,余弦相似度和欧几里得距离

1.余弦相似度同过两个向量的夹角的余弦值来判断两个向量的相似度。余弦值取值[-1,1],越接近1&#xff0c;两向量夹角越小&#xff0c;越相似。图片.png二维公式&#xff1a;图片.pngn维公式&#xff1a;图片.png存在的问题[1]&#xff1a;余弦相似度更多的是从方向上区分差异&a…

App Store 排名获取。

为什么80%的码农都做不了架构师&#xff1f;>>> https://affiliate.itunes.apple.com/resources/documentation/genre-mapping/ app榜示例 &#xff0c; 取中国免费榜前10条&#xff1a; 首先访问 https://itunes.apple.com/WebObjects/MZStoreServices.woa…

使用 Playwright 对 ASP.NET Core 应用执行功能测试

前言在前面的文章中&#xff0c;我们已经介绍过 Playwright for .NET&#xff0c;它常用于自动化测试已经部署好的 Web 应用。其实&#xff0c;开发人员也可以使用它在 ASP.NET Core 应用程序中进行功能测试。功能测试功能测试是从用户角度编写&#xff0c;用于基于其要求验证系…

PHP自动查找指定文件夹下所有文件BOM和删除所有文件

2019独角兽企业重金招聘Python工程师标准>>> <?php if (isset($_GET[dir])){ //设置文件目录 $basedir$_GET[dir]; }else{ $basedir .; } $auto 1; checkdir($basedir); function checkdir($basedir){ if ($dh opendir(…

php支持cs吗,关于composer、phpmd和phpcs于windows中的安装与使用方法

Composer项目地址 https://getcomposer.org中文 http://docs.phpcomposer.com/Composer是 PHP 的一个依赖管理工具。它允许你申明项目所依赖的代码库&#xff0c;它会在你的项目中为你安装他们。一、安装Composer官网有详细介绍安装方法&#xff0c;包括windows和linux系统。以…

基于ASP.NET Core api 的服务器事件发送

现如今程序员对Web API的调用已经是轻车熟路。但是传统的api调用都是拉模式&#xff0c;也就是主动发起请求去调用一个api.但是程序员往往对另一种很有用的模式很陌生&#xff0c;即推模式。拉模式 - 主动调用并获取结果的模式。推模式 - 订阅并接受数据推送的模式。今天要介绍…

Android之解决java.lang.NoSuchMethodError:android.os.powerManager.isInteractive问题

1、问题 再三星平板(Android 4.2.2系统)我们代码powerManager调用了函数isInteractive方法,出现下面错误 java.lang.NoSuchMethodError:android.os.powerManager.isInteractive 2、解决办法 1、一开始想用try catch来解决,肯定不行,功能没实现,而且进程还是会挂 2…