Silverlight专题(9)-WCF通信(2)

it2022-05-05  105

在上文我粗略的介绍了如何创建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

相关资源:各显卡算力对照表!

最新回复(0)