在前面幾篇文章中,分別就WCF如何與Ajax交互,如何返回json數據給Ajax,如何為ExtJs控件提供數據,如何用Http的訪問方式異步調用Restful的WCF服務,本文著重講述如何用Restful方式調用WCFl進行文件的上傳和下載。在前面的文章中,曾經寫過Restful的WCF支持兩種格式的請求和響應的數據格式:1)XML 2) JSON。事實上WCF不光支持上述兩種格式,它還支持原生數據(Raw,來源於Carlos' blog)。這樣一來,WCF的Restful方式實際上支持任意一種格式的,因為原生的即表明可以是任意一種格式,WCF從客戶端到服務端,從服務端到客戶端都會保持這種數據的原來的數據格式。通過查閱MSDN中WebMessageEncodingBindingElement 類的說明:也能找到上述的論證
首先總結一下如何在Restful的WCF的服務端和客戶端傳遞原生的數據(Raw),在WCF中,返回值或者參數為System.IO.Stream或者System.IO.Stream的派生類型的時候,加配上HTTP請求和Restful服務操作響應消息中的ContentType,便能實現原生數據的傳輸。
下面通過一個上傳和下載圖片文件的項目示例來演示如上的結論。
第一步:在VS2008中,創建一個解決方案:WcfBinaryRestful,包括四個項目:如下圖所示:
其中各個項目的說明如下表所述: 項目名稱 說明 WcfBinaryRestful.Contracts WCF服務的契約部分 WcfBinaryRestful.Service WCF服務具體實現部分 WcfBinaryRestful.Host WCF服務的Console程序的承載程序 WcfBinaryRestful.Client 客戶端
第二步:在WcfBinaryRestful.Contracts中創建並設計服務契約IService.cs,代碼如下:
IService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace WcfBinaryRestful.Contracts
{
[ServiceContract]
public interface IService
{
[OperationContract]
System.IO.Stream ReadImg();
[OperationContract]
void ReceiveImg(System.IO.Stream stream);
}
}
其中ReadImg方法用於提供jpg圖片文件,供客戶端下載,而ReceiveImg用於接收客戶端上傳的jpg圖片
第三步:在WcfBinaryRestful.Service項目中創建並設計服務具體實現類:Service.cs
Service.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Web;
using System.Drawing;
using System.Diagnostics;
namespace WcfBinaryRestful.Service
{
public class Service : Contracts.IService
{
[WebInvoke(Method = "*", UriTemplate = "ReadImg")]
public System.IO.Stream ReadImg()
{
string runDir = System.Environment.CurrentDirectory;
string imgFilePath = System.IO.Path.Combine(runDir, "jillzhanglogo.jpg");
System.IO.FileStream fs = new System.IO.FileStream(imgFilePath, System.IO.FileMode.Open);
System.Threading.Thread.Sleep(2000);
WebOperationContext.Current.OutgoingResponse.ContentType = "image/jpeg";
return fs;
}
[WebInvoke(Method = "*", UriTemplate = "ReceiveImg")]
public void ReceiveImg(System.IO.Stream stream)
{
Debug.WriteLine(WebOperationContext.Current.IncomingRequest.ContentType);
System.Threading.Thread.Sleep(3000);
string runDir = System.Environment.CurrentDirectory;
string imgFilePath = System.IO.Path.Combine(runDir, "ReceiveImg.jpg");
Image bmp = Bitmap.FromStream(stream);
bmp.Save(imgFilePath);
}
}
}
第四步:用配置的方式,創建服務承載項目:WcfBinaryRestful.Host。並使得服務可以用Restful方式訪問。
Host.cs
Host.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace WcfBinaryRestful.Host
{
public class Host
{
static void Main()
{
using (ServiceHost host = new ServiceHost(typeof(Service.Service)))
{
host.Open();
Console.WriteLine("服務已經啟動!");
Console.Read();
}
}
}
}
App.config
App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="WcfBinaryRestful.Service.Service">
<host>
<baseAddresses>
<add baseAddress=">
</baseAddresses>
</host>
<endpoint address="" binding="webHttpBinding" contract="WcfBinaryRestful.Contracts.IService" behaviorConfiguration="WcfBinaryRestfulBehavior"></endpoint>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="WcfBinaryRestfulBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
第五步:實現客戶端程序
Form1.cs
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WcfBinaryRestful.Client
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
System.Net.WebClient wc;
private void button1_Click(object sender, EventArgs e)
{
wc = new System.Net.WebClient();
SaveFileDialog op = new SaveFileDialog();
if (op.ShowDialog() == DialogResult.OK)
{
wc.DownloadFileAsync(new Uri(""), op.FileName);
wc.DownloadFileCompleted += new AsyncCompletedEventHandler(wc_DownloadFileCompleted);
button2.Enabled = true;
button1.Enabled = false;
}
}
void wc_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
if (e.Cancelled)
{
button2.Enabled = false;
button1.Enabled = true;
MessageBox.Show("用戶已經取消下載!");
return;
}
using (System.Net.WebClient wc = e.UserState as System.Net.WebClient)
{
button2.Enabled = false;
button1.Enabled = true;
MessageBox.Show("下載完畢!");
}
}
private void button2_Click(object sender, EventArgs e)
{
if (wc != null)
{
wc.CancelAsync();
}
}
System.Net.WebClient uploadWc = new System.Net.WebClient();
private void button3_Click(object sender, EventArgs e)
{
OpenFileDialog op = new OpenFileDialog();
op.Filter = "jpg文件(*.jpg)|*.jpg";
if (op.ShowDialog() == DialogResult.OK)
{
uploadWc.Headers.Add("Content-Type", "image/jpeg");
System.IO.FileStream fs = new System.IO.FileStream(op.FileName,System.IO.FileMode.Open);
byte[] buffer = new byte[(int)fs.Length];
fs.Read(buffer, 0, (int)fs.Length);
fs.Close();
uploadWc.UploadDataCompleted += new System.Net.UploadDataCompletedEventHandler(uploadWc_UploadDataCompleted);
uploadWc.UploadDataAsync(new Uri(""), buffer);
button3.Enabled = false;
button4.Enabled = true;
}
}
void uploadWc_UploadDataCompleted(object sender, System.Net.UploadDataCompletedEventArgs e)
{
if (e.Cancelled)
{
button3.Enabled = true;
button4.Enabled = false;
MessageBox.Show("用戶已經取消上傳!");
return;
}
MessageBox.Show("完成上傳!");
button3.Enabled = true;
button4.Enabled = false;
}
private void button4_Click(object sender, EventArgs e)
{
uploadWc.CancelAsync();
}
}
}
設置好多啟動項目調試後,調試,出現如下的運行界面:
1.服務承載程序運行界面圖:
2.客戶端運行界面圖:
點擊開始下載按鈕,選擇一個下載文件的保存位置,等待一會後,會提示下載成功,如下圖所示:
打開剛才選擇下載文件的保存位置,便能發現已經成功下載了jpg的圖片文件:
當然順便還可以溫習一下如何異步調用Restful的WCF服務,點擊取消下載可以停止下載,不再多說
點擊開始上傳,選擇一個要上傳的jpg圖片,等待幾秒鐘,便能收到上傳成功的對話框,如下圖所示:
找到服務承載程序所在目錄,便能看到上傳的jpg圖像文件: