消息(4)——WS附件传输,包体中的base64编码附件

简介: Soap包中可以存放数据的地方可以是soap头也可以是soap body部分。其中body部分是必须的,是重要的数据存放位置。Soap头中也可以放一些数据,例如Web服务中的安全中用户检测。例如: 如果添加soap头,那么先要有一个从SoapHeader派生的类: public class Se...

Soap包中可以存放数据的地方可以是soap头也可以是soap body部分。其中body部分是必须的,是重要的数据存放位置。Soap头中也可以放一些数据,例如Web服务中的安全中用户检测。例如:

如果添加soap头,那么先要有一个从SoapHeader派生的类:

public class SelfHeader : SoapHeader

{

    public string UserName { get; set; }

}

 

然后web服务中先定义一个公共成员:

public SelfHeader _soapHeader;

 

然后在需要添加soap头的方法上添加soap头标签:

[WebMethod]

[SoapHeader("_soapHeader")]

public string HelloWorld()

{

if (_soapHeader.UserName != "zhao")

return "用户禁止访问!";

return "Hello World";

}

 

在客户端进行访问服务时,须设置header属性:

public void TestSimpleSoap()

{

    ws.SelfService client = new ws.SelfService();

    ws.SelfHeader _header = new ws.SelfHeader();

    _header.UserName = "zzz";

 

    client.SelfHeaderValue = _header;

    Console.WriteLine(client.HelloWorld());

}

 

现在看一下现在的soap包的情况:

请求:

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope

  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"

  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <soap:Header>

    <SelfHeader xmlns="http://192.168.1.105/">

      <UserName>zzz</UserName>

    </SelfHeader>

  </soap:Header>

  <soap:Body>

    <HelloWorld xmlns="http://192.168.1.105/" />

  </soap:Body>

</soap:Envelope>

 

现在添加了header部分。

 

.net web服务中为soap添加附件。这里为什么说.net web服务呢?

这里说明一下web服务的概念:web service是基于xmlhttp的一种服务,它的通信协议主要基于SOAP(这是缩写应该全大写,但大家明白就行),通过WSDL来描述服务,通过UDDI来发布服务。

Web服务不是只有.net才有,.net中提供的web服务相关的定义,发布,发现等,及生成代理,应用。这些只是.netweb服务的一种帮助,或说.net提供了一套web服务的工具,用于创建,发布和应用。

 

Soap包中可以存放数据的位置可以是头,更重要且必须的是包体部分。那么对于附件,可以以格式化的数据存放于包体部分。

现在以包体部分来存储一个文本文件,目的很明确,那么文本文件内容以怎样的格式存放于包体呢?

第一种:文本文件中的内容以字串格式存在

 

[WebMethod]

public void SaveText(string strContent,string strFileName)

{

StreamWriter writer=File.CreateText("k:\\"+strFileName+".txt");

writer.WriteLine(strContent);

writer.Close();

}

这个方法将字串保存为utf-8的文本文件

 

客户端:

[Test]

public void TestSaveText()

{

StreamReader sr = new StreamReader

(@"k:\client.txt",Encoding.Default);

    string strTemp = sr.ReadToEnd();

    sr.Close();

 

    ws.SelfService client = new ws.SelfService();

    client.SaveText(strTemp, "server");

}

gb2312文本中读取内容,然后存在包体中向服务传递。可以看下现在的包的内容:

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope

  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"

  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <soap:Body>

    <SaveText xmlns="http://192.168.1.105/">

      <strContent>杩欐槸娴嬭瘯锛乤bc</strContent>

      <strFileName>server</strFileName>

    </SaveText>

  </soap:Body>

</soap:Envelope>

 

其中乱码部分就是内容(乱码其实并不乱),可以所这部分拷贝到一个utf-8编码下的记事本中,然后另存为gb2312格式,可以看到认识的汉字了。

内容就是:这是测试!abc

 

第二种,二进制文件例如图片以base64编码存放

其实这个文件可以直接以二进制格式来传递,但如果要保存这个包,那么须对持久化的数据进行双向的格式化,使它的数据格式不会在转化时丢失或增加,在消息1中:

http://www.cnblogs.com/jams742003/archive/2010/03/30/1700605.html

给出了通过base64和支持8位字符编码的28591页的字符集ISO8859-1

 

(一)base64来存放二进制图片

服务端:

[WebMethod]

public void SaveImages(string strBase64Content)

{

//ISO

byte[] bb = Convert.FromBase64String(strBase64Content);//iso字节

Encoding encoding = Encoding.GetEncoding(28591);

string strReturn = encoding.GetString(bb);

 

FileStream fs = File.Create(@"k:\soapPic.gif");

fs.Write(bb, 0, bb.Length);

fs.Close();

}

 

客户端:

[Test]

public void TestSaveImage()

{

    //1 iso

    Encoding _encoding = Encoding.GetEncoding(28591);

    StreamReader sr = new StreamReader(@"k:\x1.gif", _encoding);

    string strTemp = sr.ReadToEnd();

    sr.Close();

 

    //2 base64

    byte[] bb = _encoding.GetBytes(strTemp);

    string strBase64 = Convert.ToBase64String(bb);

 

    ws.SelfService client = new ws.SelfService();

    client.SaveImages(strBase64);

}

看一下现在的soap包:

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope

  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"

  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <soap:Body>

    <SaveImages xmlns="http://192.168.1.105/">

      <strBase64Content>DggAOw==</strBase64Content>

    </SaveImages>

  </soap:Body>

</soap:Envelope>

 

其中的粗体部分就是图片的内容,我省略了大部分,只留个小段。

 

(二)以二进制来传递但不保存文本

在进行base64的转换过程中要有性能损失,多一步就多消耗。因为现在不用对图片进行文本保存,那么这种持久不必要考虑,只要把图片存储下来就可以了。那么现在以二进制传递来存储图片。

服务端:

[WebMethod]

public void SaveBinaryImages(byte[] bb)

{

FileStream fs = File.Create(@"k:\soapPicBinary.gif");

fs.Write(bb, 0, bb.Length);

fs.Close();

}

 

客户端:

[Test]

public void TestSaveBinaryImage()

{

    FileStream fs = new FileStream(@"k:\x1.gif",FileMode.Open);

    byte[] bb=new byte[fs.Length];

     fs.Read(bb,0,bb.Length);  

    fs.Close();

 

    ws.SelfService client = new ws.SelfService();

    client.SaveBinaryImages(bb);

}

 

现在的soap包情况:

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope

  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"

  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <soap:Body>

    <SaveBinaryImages xmlns="http://192.168.1.105/">

      <bb>DggAOw==</bb>

    </SaveBinaryImages>

  </soap:Body>

</soap:Envelope>

 

这个包我也省略了一部分。从上面两个包分析,原来,在.net web服务里,对包体中的附件的二进制附件传递是以base64编码来进行的,所以soap中包体中的附件的转换带来的是性能上的损失。

 

在进行soap消息传递过程中,经常要把各种附件一起发送,而这些附件通过是二进制格式。在soap规范中有对附件的描述,那就是使用MIME类型以URI模式引用MIME部件。对于web服务的工具来说,并不是所有的工具都提供了对soap附件的支持,例如.net web服务。但微软推出了基于DIME的附件解决方案,并通过WSEweb服务增强)来支持web服务的MTOM消息优化传输,当然在WCF中更是支持MTOMMTOM 是一种机制,用来以原始字节形式传输包含 SOAP 消息的较大二进制附件,从而使所传输的消息较小。

Base64编码以3个字节编码规则为4个字节,多出三分之一的容量,对于base64编码请见:

http://www.cnblogs.com/jams742003/archive/2010/03/26/1696876.html

 

soap消息包,信念xml格式的soap体消息,以及信封中未定义的但与消息有关的任意数据格式的其它实体。soap消息包通过MIMEMultipart/related媒体类型构建,每个部件都嵌入MIME边界(bundary,在Content-Type报头中定义)。每个MIME部件都有报头信息如:

Content-Type:表示数据的类型

Content Transfer-encoding:表示编码

Content-ID:表示引用内容的标识符

对于MIME消息的根部件要包含soap封套,且Content-type要设置为text/xml

 

下边是一个带有MIME格式附件的soap包:

 

Content-Type:text/xml; charset=UTF-8

Content-Transfer-Encoding: binary

Content-ID:<SOAP-ENV:Envelop>

  <?xml version="1.0" encoding="UTF-8"?>

  <soapenv:Envelope>

    <soapenv:Header>

    </soapenv:Header>

    <soapenv:Body>

    </soapenv:Body>

  </soapenv:Envelope>

 

--==_Part_20081204084150203==

Content-Type:text/plain

Content-Transfer-Encoding:binary

Content-ID:<attachment0.txt>

aaaaaaaaaaaaaaaaaaaaaaaaaaa

--==_Part_20081204084150203==

Content-Type:image/jpeg

Content-Transfer-Encoding:binary

Content-ID:<attachment1.jpg>

......JFIF.....d.d.....C...

--==_Part_20081204084150203==--

 

以上就是一个完整的mime附件的soap包。

 

博客园大道至简

http://www.cnblogs.com/jams742003/

转载请注明:博客园

目录
相关文章
|
语音技术
发送octet-stream格式的请求返回乱码处理
octet-stream格式的请求返回乱码处理
|
9月前
|
前端开发 Python 微服务
flask.send_file实现文件下载、文件传输和二进制流传输
在使用flask框架时,我们有时需要向前端传输文件。或者需要用户访问一个url时直接下载文件。这时可以使用flask.send_file()函数来实现相关的操作。
1094 0
|
JSON 数据格式 Python
python POST发送多个段(如json消息+文件)
python POST发送多个段(如json消息+文件)
163 0
|
Java
通过后台Http请求的形式实现文件的上传与传输
在开发中,我们可能会遇到两个不同的系统之间进行文件传输的需求,由于没有对应的界面操作,所以,此时就需要通过java后台代码的形式来实现文件的上传操作,本文主要讲解如何通过后台方法的形式来实现文件的上传功能,并能实现相应的接收功能。
1103 0