在上文我粗略的介绍了如何创建WCF Service,并在客户端调用生成的WCF Service来取得数据
本文将用一个上传程序来继续介绍下Silverlight中的WCF Service应用
调用WCF Service的时候,并没有一个DownloadProcessChanged之类的事件来反馈已经上传了多少
那么我们如何来实现在客户端实时展示当天已经上传了多少呢?
我们可以把文件分成很多块,逐次上传一小部分(比如2K,4K,8K等等)
1。首先我们还是按照Silverlight专题(9)-WCF通信(1)这个教程中所示的先创建个新的Silverlight工程
并添加进一个Silverlight-Enabled WCF Service(我取名为DownloadService,以前随便去的名字,懒得改了)
其里面含有的操作契约如下:
1 [ServiceContract(Namespace = "" )] 2 [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 3 public class DownloadService 4 { 5 [OperationContract] 6 public string UploadImg( string fileName, byte [] fileData, bool firstChunk, bool lastChunk) 7 { 8 if ( ! File.Exists(@HostingEnvironment.ApplicationPhysicalPath + @" /Uploads/ " + fileName)) 9 { 10 string tmpExtension = " _tmp " ; 11 string tempFileName = fileName + tmpExtension; 12 if (firstChunk) 13 { 14 fileName += tmpExtension; 15 if (File.Exists(@HostingEnvironment.ApplicationPhysicalPath + tempFileName)) 16 { 17 File.Delete(@HostingEnvironment.ApplicationPhysicalPath + tempFileName); 18 } 19 } 20 21 FileStream fs = File.Open(@HostingEnvironment.ApplicationPhysicalPath + tempFileName, FileMode.Append); 22 fs.Write(fileData, 0 , fileData.Length); 23 fs.Close(); 24 25 if (lastChunk) 26 { 27 // Rename file to original file 28 File.Move(@HostingEnvironment.ApplicationPhysicalPath + tempFileName, @HostingEnvironment.ApplicationPhysicalPath + " /ClientBin/Uploads/ " + fileName); 29 } 30 } 31 32 return " ./Uploads/ " + fileName; 33 } 34 }Upload这个操作契约的输入参数有文件名,文件的比特数组,firstChunk用来表示是否传输的是文件的第一个包
lastChunk代表文件的包是不是最后一个包
如果还不是最后一个包时,将传输过来的文件的文件扩展名加上后缀_tmp来存放
一旦lastChunk为true时,将该文件存为原文件名
2.实现客户端的界面
我们需要三个东西
一个用来调用选择上传文件对话框的Button
一个用来展示上传进度的进度条
一个用来展示结果的Image控件
(我设置为只能上传JPG或者PNG文件,结果返回一个上传后的图片的相对路径)
代码如下:
1 < UserControl x:Class = " ReadImageTest.Page " 2 xmlns = " http://schemas.microsoft.com/winfx/2006/xaml/presentation " 3 xmlns:x = " http://schemas.microsoft.com/winfx/2006/xaml " > 4 < StackPanel x:Name = " LayoutRoot " Background = " #3C3C3C " > 5 < Grid > 6 < Image x:Name = " img " Width = " 800 " Height = " 600 " /> 7 < ProgressBar x:Name = " pb " Height = " 20 " Width = " 400 " Maximum = " 1 " Visibility = " Collapsed " /> 8 </ Grid > 9 < Button Margin = " 0,5 " x:Name = " uploadBtn " Content = " Upload " Padding = " 8,4 " FontSize = " 15 " HorizontalAlignment = " Center " Click = " uploadBtn_Click " /> 10 </ StackPanel > 11 </ UserControl >3.具体底层的控制代码
a.选择上传文件对话框的实现如下
1 public void uploadBtn_Click( object sender, RoutedEventArgs e) 2 { 3 OpenFileDialog ofd = new OpenFileDialog(); 4 ofd.Filter = " JPG Files|*.jpg|PNG Files|*.png " ; 5 ofd.Multiselect = false ; 6 7 if (( bool )ofd.ShowDialog()) 8 { 9 this .pb.Visibility = Visibility.Visible; 10 this .img.Opacity = 0 ; 11 dataSent = 0 ; 12 stream = ofd.File.OpenRead(); 13 dataLength = stream.Length; 14 if (dataLength > 16384 ) 15 { 16 firstChunk = true ; 17 lastChunk = false ; 18 fileName = ofd.File.Name; 19 byte [] buffer = new byte [ 4 * 4096 ]; 20 int read = stream.Read(buffer, 0 , buffer.Length); 21 dataSent += read; 22 if (read != 0 ) 23 { 24 if (dataSent == dataLength) 25 lastChunk = true ; 26 client.UploadImgAsync(fileName, buffer, firstChunk, lastChunk); 27 firstChunk = false ; 28 } 29 } 30 31 else 32 { 33 MessageBox.Show( " The upload file is too small! " ); 34 } 35 } 36 }我设置了每个包的大小是16K
也就是每次调用WCF Service最多只能传16K的东西
BTW:其中Client的定义为 private DownloadServiceRef.DownloadServiceClient client;
b.展示上传进度并显示最终上传结果
1 void client_UploadImgCompleted( object sender, ReadImageTest.DownloadServiceRef.UploadImgCompletedEventArgs e) 2 { 3 if (dataSent < dataLength) 4 { 5 byte[] buffer = new byte[4 * 4096]; 6 int read = stream.Read(buffer, 0, buffer.Length); 7 dataSent += read; 8 this.pb.Value = (double)dataSent / dataLength; 9 if (read != 0) 10 { 11 if (dataSent == dataLength) 12 lastChunk = true; 13 client.UploadImgAsync(fileName, buffer, firstChunk, lastChunk); 14 firstChunk = false; 15 } 16 } 1718 else 19 { 20 this.pb.Visibility = Visibility.Collapsed; 21 this.img.Opacity = 1; 22 this.img.Source = new BitmapImage(new Uri(e.Result, UriKind.RelativeOrAbsolute)); 23 } 24}每上传完一个包就更新下上传进度条
如果传送的包的大小已经等于文件大小时,隐藏进度条,并展示上传的图片
Silverlight目前对WCF的支持虽然只局限在普通的HttpBinding,但是功能也还算强大
本文只是小试牛刀,展示了个小小的图片上传工具实现,希望能起到抛砖引玉的作用
源代码下载地址如下:
转载于:https://www.cnblogs.com/ibillguo/archive/2008/10/26/1320023.html
相关资源:各显卡算力对照表!