(1) HTTP プロトコルによる WCF サービスアプリケーションプログラムの構築方法を習得する。
(2) WCF クライアントとサーバー間のメッセージ交換モードをマスターします。
(3) 契約書の設計と実施方法を習得する。
(4) WCF と HTTP の関連するバインド設定に精通している。
(5) ストリームの読み書き操作方法を習得する。
同じソリューション内でサーバープログラムとクライアントプログラムを別々に記述し、HTTPとストリーミングを利用してファイルダウンロード機能を実現します。図 A-4 は、クライアント プログラムの実行結果を示しています。
具体的な要件
(1) 基本機能: ファイルのダウンロード (必須)。
(2) 機能拡張:ファイルアップロード(オプション)。
重要なポイント: HTTP プロトコルでの WCF サービス アプリケーション プログラムの構築方法をマスターする; WCF クライアントとサーバー間のメッセージ交換モードをマスターする; アグリーメントの設計と実装方法をマスターする; WCF と HTTP の関連バインド設定に精通する。
難易度: プロトコルの設計と実装方法をマスターします。
MainWindow.xaml
Window x:Class="shiyan4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:shiyan4"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<GroupBox Grid.Row="0" Header="请选择可下载的文件">
<ListBox x:Name="lb1"/>
</GroupBox>
<Border Grid.Row="1" Background="Beige" Padding="0 5 0 5">
<Button x:Name="btnDownload" Content="开始下载" Width="100" Height="19" VerticalAlignment="Top" Click="btnDownload_Click"/>
</Border>
<GroupBox Grid.Row="2" Header="下载信息">
<ScrollViewer>
<StackPanel TextBlock.LineHeight="20">
<TextBlock x:Name="tb1" TextWrapping="Wrap" Margin="0 10 0 0"/>
</StackPanel>
</ScrollViewer>
</GroupBox>
</Grid>
</Window>
MainWindow.xaml.cs
using ServiceReference1;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace shiyan4
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Loaded += MainWindow_Loaded;
}
String[] info;
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
Service1Client client=new Service1Client();
info = client.getFilesInfo();
foreach (String file in info)
{
String[] s = file.Split(",");
Label label = new Label();
label.Content = String.Format("文件名:{0},文件长度:{1}字节", s[0], s[1]) ;
lb1.Items.Add(label) ;
}
client.Close();
if(lb1.Items.Count > 0)
{
lb1.SelectedIndex = 0;
btnDownload.IsEnabled = true;
}
else
{
btnDownload.IsEnabled = false;
addInfo("找不到可以下载的文件!");
}
}
private void addInfo(String info)
{
tb1.Text += info;
tb1.Text += Environment.NewLine;
}
private void btnDownload_Click(object sender, RoutedEventArgs e)
{
tb1 .Text = "";
String[] a = info[lb1.SelectedIndex].Split(",");
addInfo(String.Format("正在下载{0}", a[0]));
ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
Stream stream = client.DownloadStream(a[0]);
String path=System.IO.Path.Combine(Environment.CurrentDirectory, a[0]);
streamToFile(stream, path);
}
private void streamToFile(Stream stream,String path)
{
const int BUFSIZE = 4096;
byte[] buffer = new byte[BUFSIZE];
FileStream fileStream = File.Open(path, FileMode.Create, FileAccess.Write);
int count=0;
int all = 0;
while ((count = stream.Read(buffer, 0, BUFSIZE)) > 0)
{
fileStream.Write(buffer, 0, count);
all += count;
}
stream.Close();
fileStream.Close();
addInfo(String.Format("下载完成,共下载{0}字节,文件保存到{1}", all, path));
}
}
}
IService1.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace WcfService1
{
// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IService1”。
[ServiceContract]
public interface IService1
{
[OperationContract]
List<String> getFilesInfo();
[OperationContract]
Stream DownloadStream(string fileName);
// TODO: 在此添加您的服务操作
}
}
Service1.svc
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace WcfService1
{
// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码、svc 和配置文件中的类名“Service1”。
// 注意: 为了启动 WCF 测试客户端以测试此服务,请在解决方案资源管理器中选择 Service1.svc 或 Service1.svc.cs,然后开始调试。
public class Service1 : IService1
{
public static List<String> filesInfo;
public static String path;
public Stream DownloadStream(string fileName)
{
String filePath=Path.Combine(path, fileName);
FileStream fileStream=File.OpenRead(filePath);
return fileStream;
}
public List<string> getFilesInfo()
{
if (filesInfo == null)
{
filesInfo = new List<String>();
path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "DownloadFiles");
DirectoryInfo directoryInfo = new DirectoryInfo(path);
var f = directoryInfo.EnumerateFiles();
foreach ( var f2 in f)
{
//格式:文件名,以字节为单位的文件长度
filesInfo.Add(String.Format("{0},{1}",f2.Name,f2.Length));
}
}
return filesInfo;
}
}
}
Web.config (追加された構成ファイルはここにあります)
<bindings>
<basicHttpBinding>
<binding name="b1" transferMode="Buffered" textEncoding="utf-8" messageEncoding="Text">
<security mode="None"/>
</binding>
</basicHttpBinding>
</bindings>
<!-- <protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping> -->
<services>
<service name="WcfService1.Service1">
<endpoint binding="basicHttpBinding" bindingConfiguration="b1" contract="WcfService1.IService1"/>
</service>
</services>
午後中ずっと書いていて、疲れて死にたいです。