WCF异步上传相关技巧分享

开发 开发工具
WCF异步上传的实现,可以使我们对大文件进行简单的上传。那么在这篇文章中,我们将会为大家详细介绍一下这方面的相关应用。

WCF总对于文件的传输方式可以通过各种方法来实现,而且对于大文件的传输也能轻松的实现。在这里我们可以通过WCF异步上传的方法来详细介绍一下这方面的应用知识,以此来加深大家对这方面的认识程度。#t#

在WCF下作大文件的上传,首先想到使用的就是Stream,这也是微软推荐的使用方式。处理流程是:首先把文件加载到内存中,加载完毕后传递数据。这种处理方式对小文件,值得推荐,比如几K,几十k的图片文件,文本文件对大文件就不适用,比如10G的电影,把10G的数据加载到缓存中再传递,这是不可想象的。这个时候我们想到的就是断点续传。由于数据量很大。会导致当前程序阻塞,所以采用异步发送的方式,以进度条显示出来,这也是本篇文章所要实现的功能. 另外,目前BasicHttpBinding, NetTcpBinding, 和NetNamedPipeBinding 支持流处理模型,其他的不支持,这也影响stream的使用。

解释几个重要的概念以及实现的方式:

1、WCF异步上传之断点续传:就是在上一次下载/上传断开的位置开始继续下载/上传。微软已经提供好了这样的方法: BinaryWriter 这个是二进制的写入器,看下面:

namespace System.IO  
{  
public class BinaryWriter : IDisposable  
{  
public virtual long Seek(int offset, SeekOrigin origin); 
//设置当前流中的位置,***个参数表示偏移量,第二个参数表示偏移量的参考依据  
public virtual void Write(byte[] buffer); //把数据写入Seek方法设置的位置  
}  
}  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

2、WCF异步上传之异步线程:就是使用后台程序,不用阻塞当前线程,使用backgroundWorker组建,可以大大减少代码的编写量
下面的操作都是与WCF相关的部分。首先我们要定义一个数据契约用来传递数据:

[DataContract]  
public class FileInfo  
{  
//文件名  
[DataMember]  
public string Name { get; set; }  
//文件字节大小  
[DataMember]  
public long Length { get; set; }  
//文件的偏移量  
[DataMember]  
public long Offset { get; set; }  
//传递的字节数[DataMember]  
public byte[] Data { get; set; }  
//创建时间  
[DataMember]  
public DateTime CreateTime { get; set; }  
}  
接着定义操作的契约:  
[ServiceContract]  
public interface IFilesLoad  
{  
[OperationContract]  
List< FileInfo> GetFilesList(); //获得以已经上传的文件列表  
[OperationContract]  
FileInfo GetFiles(string fileName); 
//根据文件名寻找文件是否存在,返回文件的字节长度  
[OperationContract]   FileInfo UplodaFile(FileInfo file); //上传文件  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.

定义了契约,下面就要来实现契约,这里仅仅粘贴重要部分,在后面可以下载源代码

public Fish.DataContracts.FileInfo UplodaFile
(Fish.DataContracts.FileInfo file)  
{   string filePath = System.Configuration.ConfigurationManager.
AppSettings["filePath"] + "/" + file.Name;
//获取文件的路径,已经保存的文件名  
FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate);
//打开文件  
long offset = file.Offset; //file.Offset 
文件偏移位置,表示从这个位置开始进行后面的数据添加  
BinaryWriter writer = new BinaryWriter(fs);//初始化文件写入器   writer.Seek((int)offset, SeekOrigin.Begin);//设置文件的写入位置   writer.Write(file.Data);//写入数据   file.Offset = fs.Length;//返回追加数据后的文件位置   file.Data = null;   writer.Close();   fs.Close();   return file;  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.

下面来进行服务端得WCF配置

< system.serviceModel> 
< services> 
< !-- 文件断点续传 --> 
< service behaviorConfiguration="DefaultBehavior" 
name="Fish.ServiceImpl.FilesService">  < endpoint address="" binding="basicHttpBinding" 
bindingConfiguration ="StreamedHTTP"
 contract="Fish.ServiceInterfaces.IFilesLoad">< /endpoint>  < host>  < baseAddresses>  < add baseAddress="http://localhost:8080/Fish/FilesService"/>  < /baseAddresses>  < /host>  < /service>  < /services>  < behaviors>  < serviceBehaviors>  < behavior name="DefaultBehavior">  < serviceMetadata httpGetEnabled="true" />  < serviceDebug includeExceptionDetailInFaults="true" />  < /behavior>  < /serviceBehaviors>  < /behaviors>  < bindings>  < basicHttpBinding>  < binding name="StreamedHTTP" maxReceivedMessageSize="2000000000000"
 messageEncoding="Mtom" transferMode="Streamed">  < readerQuotas maxArrayLength="20000000"/>  < /binding>  < /basicHttpBinding>  < /bindings>  < /system.serviceModel> 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.

这里最要的是设置maxReceivedMessageSize, messageEncoding。比较重要的是设置为Mtom,可以提高30%的效率,这是wcf特意为大文件提供的。下面看客户端代码:

var fileManger = Common.ServiceBroker.FindService
< IFilesLoad>(); //创建WCF代理  
string localPath = e.Argument as string;    string fileName = localPath.Substring(localPath.LastIndexOf
('\\') + 1);//获得文件本地文件地址  
int maxSiz = 1024 * 100; //设置每次传100k    FileStream stream = System.IO.File.OpenRead(localPath); 
//读取本地文件  
Fish.DataContracts.FileInfo file = fileManger.GetFiles
(fileName); //更加文件名,查询服务中是否存在该文件  
if (file == null) //表示文件不存在   {   file = new Fish.DataContracts.FileInfo();   file.Offset = 0; //设置文件从开始位置进行数据传递   }   file.Name = fileName;   file.Length = stream.Length;   if (file.Length == file.Offset) 
//如果文件的长度等于文件的偏移量,说明文件已经上传完成  
{   MessageBox.Show("该文件已经在服务器中,不用上传!", "提示", 
MessageBoxButtons.OK, MessageBoxIcon.Warning);  
return;   }   else   {   while (file.Length != file.Offset) 
//循环的读取文件,上传,直到文件的长度等于文件的偏移量  
{   file.Data = new byte[file.Length - file.Offset 
< = maxSiz ? file.Length - file.Offset : maxSiz]; //设置传递的数据的大小   stream.Position = file.Offset; //设置本地文件数据的读取位置   stream.Read(file.Data, 0, file.Data.Length);//把数据写入到file.Data中   file = fileManger.UplodaFile(file); //上传   e.Result = file.Offset;   (sender as BackgroundWorker).ReportProgress((int)
(((double)file.Offset / (double)((long)file.Length)) * 100), file.Offset);  
if (this.backgroundWorker1.CancellationPending)   return;   }   }   stream.Close();   Common.ServiceBroker.DisposeService< IFilesLoad>(fileManger); //关闭wcf 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.

以上就是对WCF异步上传的相关介绍。

责任编辑:曹凯 来源: 博客园
相关推荐

2010-02-24 11:22:04

WCF方法重载

2009-12-22 16:03:03

WCF异常

2009-12-21 14:10:26

WCF异步调用

2010-03-01 13:06:49

WCF继承

2010-02-23 17:30:41

WCF部署于IIS

2009-12-21 14:49:27

2010-02-26 14:12:27

WCF元数据

2010-02-22 15:20:54

WCF WS-Disc

2010-02-22 17:21:02

WCF消息交换

2010-02-23 16:46:47

WCF并发能力

2010-02-25 15:25:19

WCF通道

2009-12-22 19:00:08

WCF回调

2010-02-22 13:28:05

WCF异步调用

2009-12-21 18:10:50

WCF实现事件通知

2009-12-21 11:19:50

WCF配置文件

2010-02-25 18:04:02

WCF IIS宿主

2010-03-01 15:40:04

WCF实例停用

2010-03-02 10:50:57

WCF元数据交换

2010-02-26 10:46:12

WCF行为扩展

2010-02-23 13:03:34

WCF序列化
点赞
收藏

51CTO技术栈公众号