wcf综合运用之:大文件异步断点续传

在WCF下作大文件的上传,首先想到使用的就是Stream,这也是微软推荐的使用方式。处理流程是:首先把文件加载到内存中,加载完毕后传递数据。这种处理方式对小文件,值得推荐,比如几K,几十k的图片文件,文本文件对大文件就不适用,比如10G的电影,把10G的数据加载到缓存中再传递,这是不可想象的。这个时候我们想到的就是断点续传。由于数据量很大。会导致当前程序阻塞,所以采用异步发送的方式,以进度条显示出来,这也是本篇文章所要实现的功能. 另外,目前BasicHttpBinding, NetTcpBinding, 和NetNamedPipeBinding 支持流处理模型,其他的不支持,这也影响stream的使用。
       解释几个重要的概念以及实现的方式:
       1、断点续传:就是在上一次下载/上传断开的位置开始继续下载/上传。微软已经提供好了这样的方法: BinaryWriter 这个是二进制的写入器,看下面:

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

2、异步线程:就是使用后台程序,不用阻塞当前线程,使用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); //上传文件
    }

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

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;
        }

下面来进行服务端得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>

这里最要的是设置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

最后是最后运行的效果:

代码地址:/Files/wanqiming/Upload.rar

原文链接:http://www.cnblogs.com/wanqiming/archive/2009/09/22/1571565.html

时间: 2024-10-12 08:31:36

wcf综合运用之:大文件异步断点续传的相关文章

mac下载百度云盘大文件及断点续传的方法

问题 作为资源共享平台, 百度云做的还是很出色的, "xxx site:pan.baidu.com"就可以找到很丰富的资源. 然而, 下载百度云上的文件就略蛋疼了. 早在12年的时候, 百度云还是一个良心企业, 不仅免费送容量, 而且下载不限速不限时不用客户端, 看片不会被绿*坝, 在教育网内甚至可以达到10M/s的速度. 当然现在容量已经不是什么问题了, 13年的空间大战早已让我们步入T级时代, 但是下载的各种限制着实让人伤不起. 绿*坝的存在让我们丧失了大量的片源  但作为遵纪守法

【iOS开发-网络】大文件的断点续传(断点下载)

要想实现断点续传,暂停的时候要取消connection连接, 开始下载的时候要给服务器发送头信息,告诉他要请求多长的数据,从哪里开始 //暂停 if(sender.selected) { [self.conn cancel];//取消连接 self.conn = nil; //开始 } else { //创建url NSURL *url = [NSURL URLWithString:@"http://localhost:8080/TFServer/resources/videos/minion_

jsp大文件传输断点续传源码

这里只写后端的代码,基本的思想就是,前端将文件分片,然后每次访问上传接口的时候,向后端传入参数:当前为第几块文件,和分片总数 下面直接贴代码吧,一些难懂的我大部分都加上注释了: 上传文件实体类: 看得出来,实体类中已经有很多我们需要的功能了,还有实用的属性.如MD5秒传的信息. publicclassFileInf { public FileInf(){} publicStringid=""; publicStringpid=""; publicStringpidR

Web大文件上传断点续传解决方案

最近遇见一个需要上传百兆大文件的需求,调研了七牛和腾讯云的切片分段上传功能,因此在此整理前端大文件上传相关功能的实现. 在某些业务中,大文件上传是一个比较重要的交互场景,如上传入库比较大的Excel表格数据.上传影音文件等.如果文件体积比较大,或者网络条件不好时,上传的时间会比较长(要传输更多的报文,丢包重传的概率也更大),用户不能刷新页面,只能耐心等待请求完成. 下面从文件上传方式入手,整理大文件上传的思路,并给出了相关实例代码,由于PHP内置了比较方便的文件拆分和拼接方法,因此服务端代码使用

iOS开发之网络编程--使用NSURLConnection实现大文件断点续传下载+使用输出流代替文件句柄

前言:本篇讲解,在前篇iOS开发之网络编程--使用NSURLConnection实现大文件断点续传下载的基础上,使用输出流代替文件句柄实现大文件断点续传.    在实际开发中,输入输出流用的比较少,但是用起来也是很方便的.iOS开发用到的输入输出流和在Java中的输入输出流是几乎一样的,本质也是一个意思:将网络返回的数据当做流来处理.    输入输出的理解:输入到哪里?输出到哪里?这个问题不难理解,输入输出是要站着服务器角度来思考的,下面用图来解释:    代码关键词: 1.在接收到响应头的代理

Web大文件(夹)上传(断点续传)控件-Xproer.HttpUploader6

版权所有 2009-2017荆门泽优软件有限公司 保留所有权利 官方网站:http://www.ncmem.com/ 产品首页:http://www.ncmem.com/webapp/up6.2/index.asp 在线演示:http://www.ncmem.com/products/up6.3/index.htm 产品介绍:http://www.cnblogs.com/xproer/archive/2012/10/26/2741264.html 升级日志:http://www.cnblogs.

HTML5 大文件断点续传完整思路整理

需求: 支持大文件批量上传(20G)和下载,同时需要保证上传期间用户电脑不出现卡死等体验: 内网百兆网络上传速度为12MB/S 服务器内存占用低 支持文件夹上传,文件夹中的文件数量达到1万个以上,且包含层级结构. 支持PC端全平台操作系统,Windows,Linux,Mac 支持文件和文件夹的批量下载,断点续传.刷新页面后继续传输.关闭浏览器后保留进度信息. 支持文件夹批量上传下载,服务器端保留文件夹层级结构,服务器端文件夹层级结构与本地相同. 支持断点续传,关闭浏览器或刷新浏览器后仍然能够保留

基于Nodejs的大文件上传之断点续传

接着<扒一扒Nodejs formidable的onPart>和<也说文件上传之兼容IE789的进度条---丢掉flash>:前面已完成兼容IE789的大文件上传:无flash的低版本进度条,高版本的分段上传,并已为断点续传做好铺垫: 说什么做好铺垫,原本以为Nodejs端已没问题,只剩前端依靠HTML5接着监听abort事件,保存中断时上传到第几块了(断点续传只支持文件比较大,然后意外上传中断了,暂时定50M开启断点续传吧),通过文件内容hash和该文件唯一上传token来记录断

WCF利用Stream上传大文件

WCF利用Stream上传大文件 转自别人的文章,学习这个例子,基本上wcf也算入门了,接口用法.系统配置都有了 本文展示了在asp.net中利用wcf的stream方式传输大文件,解决了大文件上传问题.主要是存档方便以后遇到该问题是来查阅.贴出部分代码,如果有疑惑或需要完整代码的请留言 WebForm1.aspx.cs protected void Button1_Click(object sender, EventArgs e) {             FileData file = n