1. Web Service 和 SOAP
XML Web Service 是通過(guò) SOAP(簡(jiǎn)單對(duì)象訪(fǎng)問(wèn)協(xié)議)協(xié)議進(jìn)行通信的,而 SOAP 消息是利用 XML 進(jìn)行描述的。使用 XML 描述 SOAP 消息的好處是使得 Web Service 可以跨平臺(tái)調(diào)用,成就了 Web Service 的巨大魅力。(關(guān)于 Web Service 的介紹請(qǐng)看 《XML Web Service 基礎(chǔ)》 )
由于 SOAP 消息是用 XML 進(jìn)行描述的,如果需要通過(guò) Web Service 傳輸二進(jìn)制數(shù)據(jù),就必須在傳輸之前,將二進(jìn)制數(shù)據(jù)轉(zhuǎn)換成 Base64 編碼的字符串,數(shù)據(jù)傳送到了接收方后,再將 Base64 編碼的字符串還原為二進(jìn)制數(shù)據(jù)。這樣產(chǎn)生了一個(gè)問(wèn)題,經(jīng)過(guò) Base64 編碼后,二進(jìn)制數(shù)據(jù)的體積會(huì)膨脹,從而影響了數(shù)據(jù)傳輸?shù)男阅堋?
2. WSE 和 WS-Attachment
為了解決這個(gè)問(wèn)題,微軟在 Web Service Enhancements (WSE) 中實(shí)現(xiàn)了 WS-Attachment 規(guī)范,從而避免了在 Web Service 傳輸二進(jìn)制數(shù)據(jù)時(shí),需要對(duì)二進(jìn)制數(shù)據(jù)進(jìn)行 Base64 編碼/解碼處理。WS-Attachment 的工作原理是將二進(jìn)制數(shù)據(jù)作為 SOAP 消息的附件(類(lèi)似郵件的附件),而不作為 SOAP 消息的內(nèi)容進(jìn)行發(fā)送。這樣可以避免對(duì)二進(jìn)制數(shù)據(jù)進(jìn)行 XML 序列化(XML 序列化過(guò)程中會(huì)對(duì)二進(jìn)制數(shù)據(jù)進(jìn)行 Base64 編碼),因?yàn)樾蛄谢闹皇?SOAP 消息的內(nèi)容。(關(guān)于如何使用 WSE 附件請(qǐng)看 《Using Web Services Enhancements to Send SOAP Messages with Attachments》 )
微軟發(fā)布的 WSE 只支持桌面平臺(tái)的 .NET Framework,不支持智能設(shè)備平臺(tái)的 .NET Comapct Framework。如果你想在 Windows Mobile 或 Windows CE 平臺(tái)上使用 WS-Attachment 傳輸二進(jìn)制數(shù)據(jù),那就要使用 OpenNETCF SDF 庫(kù)了。OpenNETCF SDF 實(shí)現(xiàn)了 WSE2 里面大部分的 WS-* 規(guī)范,其中包括 WS-Attachment。為 .NET CF 平臺(tái)實(shí)現(xiàn)這些 WS-* 規(guī)范的并非OpenNETCF,而是
brains-N-brawn
。在 OpenNETCF v1.2 之后才加入這部分功能。
3. 在 Windows Mobile 使用 WS-Attachment
我們將通過(guò)構(gòu)建一個(gè)上傳和下載文件的應(yīng)用來(lái)展示 WS-Attachment 在 Windows Mobile 上如何使用。構(gòu)建這個(gè)應(yīng)用我們需要實(shí)現(xiàn)一個(gè)服務(wù)器端和一個(gè)客戶(hù)端。服務(wù)器端也就是 Web Service 端,可以采用 WSE2 SP3 實(shí)現(xiàn) WS-Attachment;客戶(hù)端也就是 Windows Mobile 端,采用 OpenNETCF v2.0 實(shí)現(xiàn) WS-Attachment。我們使用 Visual Studio 2005 SP1 開(kāi)發(fā)這個(gè)應(yīng)用。
說(shuō)到這里,可能對(duì) WSE 比較熟悉的朋友就有疑問(wèn)了:既然使用 Visual Studio 2005 開(kāi)發(fā),為什么不用最新的基于 .NET 2.0 的WSE3,而使用基于 .NET 1.1 的 WSE2呢?那是因?yàn)?WSE3 已經(jīng)用一種更好的技術(shù)代替 WS-Attchment 了,那就是 MTOM。我也很不理解微軟為什么不在 WSE3 中保留 WS-Attachment,而是直接用 MTOM 將它替換掉。不過(guò)慶幸的是 WSE2 SP3 在 Visual Studio 2005 中依然能夠正常工作。
3.1 創(chuàng)建服務(wù)器端
1) 打開(kāi) Visual Studio 2005,新建一個(gè)“ASP.NET Web 服務(wù)應(yīng)用程序”項(xiàng)目,命名為“WSAttachmentService”。如果你找不到這個(gè)項(xiàng)目模版,是因?yàn)槟銢](méi)有安裝 Visual Studio 2005 SP1。
2) 為 WSAttachmentService 項(xiàng)目添加引用,在 添加引用 對(duì)話(huà)框的 .NET 選項(xiàng)卡中,選擇 Microsoft.Web.Service2 (C:\Program Files\Microsoft WSE\v2.0\Microsoft.Web.Services2.dll),并點(diǎn)擊 確定 。
3) 打開(kāi) Web.config 文件,添加如下配置項(xiàng):
< webServices >
< soapExtensionTypes >
< add type ="Microsoft.Web.Services2.WebServicesExtension,Microsoft.Web.Services2,Version=2.0.3.0,Culture=neutral,PublicKeyToken=31BF3856AD364E35" priority ="1" group ="0" />
</ soapExtensionTypes >
</ webServices >
</ system.web >
4) 打開(kāi) Service1.asmx.cs 進(jìn)行代碼編輯,刪除默認(rèn)的 HelloWorld() Web 方法,并引用3個(gè)命名空間。
using Microsoft.Web.Services2;
using Microsoft.Web.Services2.Dime;
5) 添加一個(gè)用于下載文件的 Web 方法 DownloadFile()。
public void DownloadFile()
{
SoapContextrespContext = ResponseSoapContext.Current;
DimeAttachmentdimeAttach = new DimeAttachment(
" image/jpg " ,TypeFormat.MediaType,Server.MapPath( " img01.jpg " ));
respContext.Attachments.Add(dimeAttach);
}
6) 再添加一個(gè)用于上傳文件的 Web 方法 UploadFile()。
public void UploadFile()
{
SoapContextreqContext = RequestSoapContext.Current;
byte []buffer;
using (Streamstream = reqContext.Attachments[ 0 ].Stream)
{
buffer = new byte [stream.Length];
stream.Read(buffer, 0 ,buffer.Length);
}
// 將數(shù)據(jù)寫(xiě)入磁盤(pán)文件中(需要設(shè)置相應(yīng)權(quán)限)
using (FileStreamfileStream = File.OpenWrite(Server.MapPath( " img02.jpg " )))
{
fileStream.Write(buffer, 0 ,buffer.Length);
}
}
7) 設(shè)置 WSAttachmentService 目錄的訪(fǎng)問(wèn)權(quán)限,為 Internet 來(lái)賓賬戶(hù)添加
修改
和
寫(xiě)入
權(quán)限。
3.2 創(chuàng)建客戶(hù)端
1) 在當(dāng)前解決方案新建一個(gè)“Windows Mobile 5.0 Pocket PC”智能設(shè)備項(xiàng)目,命名為“WSAttachmentMobile”。
2) 打開(kāi) Form1.cs 的窗體設(shè)計(jì)界面,添加一個(gè) PictureBox 控件(pictureBox1)到 Form1 上,再添加 Download 和 Upload 兩個(gè)菜單項(xiàng)(mniDownload 和 mniUpload)。
3) 為項(xiàng)目添加引用,在 添加引用 對(duì)話(huà)框的 .NET 選項(xiàng)卡中,選擇 OpenNETCF.Web.Service2 (C:\Program Files\OpenNETCF\Smart Device Framework 2.0\OpenNETCF.Web.Services2.dll),并點(diǎn)擊 確定 。
4) 為項(xiàng)目添加 Web 引用,在添加 Web 引用對(duì)話(huà)框中,輸入 URL 地址: http://localhost/WSAttachmentService/Service.asmx ,點(diǎn)擊地址欄右邊的 前往 按鈕,確認(rèn) Web Service 是否能夠打開(kāi),然后點(diǎn)擊 添加引用 按鈕。
5) 為項(xiàng)目添加一個(gè)類(lèi)文件 DimeServWrap.cs,代碼如下:
using System.Web.Services.Protocols;
using System.Web.Services.Description;
using OpenNETCF.Web.Services2.Dime;
namespace WSAttachmentMobile
{
public class DimeServWrap:localhost.Service1,IDimeAttachmentContainer
{
public DimeServWrap(): base ()
{
this .Url = " http://bjb-libo/WSAttachmentService/Service1.asmx "
}
DimeAttachmentCollectionrequestAttachments;
DimeAttachmentCollectionresponseAttachments;
// IDimeAttachmentContainer.RequestAttachments
public DimeAttachmentCollectionRequestAttachments
{
get
{
if (requestAttachments == null )
requestAttachments = new DimeAttachmentCollection();
return requestAttachments;
}
}
// IDimeAttachmentContainer.ResponseAttachments
public DimeAttachmentCollectionResponseAttachments
{
get
{
if (responseAttachments == null )
responseAttachments = new DimeAttachmentCollection();
return responseAttachments;
}
}
[DimeExtension]
[SoapDocumentMethod( http://tempuri.org/DownloadFile ,RequestNamespace = " http://tempuri.org/ " ,ResponseNamespace = " http://tempuri.org/ " ,Use = SoapBindingUse.Literal,ParameterStyle = SoapParameterStyle.Wrapped)]
public new void DownloadFile()
{
this .Invoke( " DownloadFile " , new object [ 0 ]);
}
[DimeExtension]
[SoapDocumentMethod( http://tempuri.org/UploadFile ,RequestNamespace = " http://tempuri.org/ " ,ResponseNamespace = " http://tempuri.org/ " ,Use = SoapBindingUse.Literal,ParameterStyle = SoapParameterStyle.Wrapped)]
public new void UploadFile()
{
this .Invoke( " UploadFile " , new object [ 0 ]);
}
}
}
DimeServWrap 類(lèi)做了幾件事:
a. 繼承了 localhost.Service1 代理類(lèi)
b. 實(shí)現(xiàn)了 OpenNETCF.Web.Services2.Dime.IDimeAttachmentContainer 接口
c. 設(shè)置了 Web Service 的 url 地址
d. 覆蓋了基類(lèi)的 DownloadFile() 和 UploadFile() 方法,并為兩個(gè)方法都加上了 DimeExtension 屬性
6) 打開(kāi) Form1.cs 代碼進(jìn)行編輯,并引用兩個(gè)命名空間:
using OpenNETCF.Web.Services2.Dime;
7) 回到 Form1 的窗體設(shè)計(jì)界面,用鼠標(biāo)雙擊 Download 菜單項(xiàng),并未 mniDownload 添加 Click 事件的處理代碼:
{
Cursor.Current = Cursors.WaitCursor;
DimeServWrapsvc = new DimeServWrap();
svc.DownloadFile();
byte []buffer;
using (Streamstream = svc.ResponseAttachments[ 0 ].Stream)
{
buffer = new byte [stream.Length];
stream.Read(buffer, 0 ,buffer.Length);
pictureBox1.Image = new Bitmap(stream);
}
using (FileStreamfileStream = File.OpenWrite( " img01.jpg " ))
{
fileStream.Write(buffer, 0 ,buffer.Length);
}
Cursor.Current = Cursors.Default;
MessageBox.Show( " Filewasdownloadedsuccessful! " );
}
8) 采用同樣的方法為 mniUpload 添加 Click 事件的處理代碼:
{
Cursor.Current = Cursors.WaitCursor;
using (FileStreamfileStream = File.OpenRead( " img01.jpg " ))
{
DimeServWrapsvc = new DimeServWrap();
DimeAttachmentdimeAttach = new DimeAttachment(
" uuid: " + Guid.NewGuid().ToString( " D " ), " image/jpg " ,
TypeFormatEnum.MediaType,fileStream);
svc.RequestAttachments.Add(dimeAttach);
svc.UploadFile();
}
Cursor.Current = Cursors.Default;
MessageBox.Show( " Filewasuploadedsuccessful! " );
}
9) 到現(xiàn)在為止,所有代碼已經(jīng)編寫(xiě)好了,我們來(lái)看看解決方案的文件組織結(jié)構(gòu),檢查一下是否有遺漏的地方:
3.3 調(diào)試程序
1) 從 Visual Studio 2005 的工具菜單打開(kāi)“設(shè)備仿真器管理”,并連接 CHS Windows Mobile 5.0 Pocket PC Emulator (我這里使用的是簡(jiǎn)體中文版的設(shè)備仿真器鏡像,你也可以使用英文版的),最后將其插入底座,使仿真器可以連接到 ActiveSync,這樣我們的仿真器就能通過(guò)網(wǎng)絡(luò)訪(fǎng)問(wèn)到桌面電腦的 Web Service 了。
2) 回到 Visual Studio 2005 中,并在設(shè)備工具欄選擇 Windows Mobile 5.0 Pocket PC Device。
3) 接下來(lái)我們可以按 F5 鍵開(kāi)始調(diào)試了,在部署過(guò)程中會(huì)安裝 .NET Compact Framework 2.0 到仿真器中(如果還沒(méi)有安裝)。
4) 程序啟動(dòng)后,先點(diǎn)擊 Download 菜單項(xiàng),從服務(wù)器端下載一個(gè)圖片文件,并顯示在窗體上,同時(shí)將圖片文件保存到設(shè)備上;接著點(diǎn)擊 Upload 菜單項(xiàng),從設(shè)備讀取剛才下載的圖片文件,并上傳到服務(wù)器端,服務(wù)器端將其保存到根目錄下。
4. 總結(jié)
在 Windows Mobile 應(yīng)用程序中利用 WS-Attachment 傳輸二進(jìn)制數(shù)據(jù),可以減少數(shù)據(jù)傳輸量,提高數(shù)據(jù)傳輸速度,從而增強(qiáng)用戶(hù)體驗(yàn)。特別是在 GPRS 和 CDMA 的低速網(wǎng)絡(luò)條件下,如果再結(jié)合數(shù)據(jù)壓縮技術(shù),將會(huì)取得顯著的效果。不過(guò),如果在局域網(wǎng)的環(huán)境下,建議不要對(duì)數(shù)據(jù)進(jìn)行壓縮。因?yàn)榫钟蚓W(wǎng)的網(wǎng)絡(luò)速度足夠快,傳輸大文件和小文件所需要的時(shí)間相差不多,而數(shù)據(jù)壓縮則需要更多的時(shí)間,所以速度反而會(huì)更慢。畢竟 Windows Mobile 設(shè)備的硬件性能是無(wú)法跟桌面電腦相比。
示例代碼下載:
WSAttachmentMobile.rar
作者:黎波
博客:http://upto.cnblogs.com/
日期:2007年3月24日
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
