wcf综合运用之:大文件异步断点续传
在WCF下作大文件的上传,首先想到使用的就是Stream,这也是微软推荐的使用方式。处理流程是:首先把文件加载到内存中,加载完毕后传递数据。这种处理方式对小文件,值得推荐,比如几K,几十k的图片文件,文本文件对大文件就不适用,比如10G的电影,把10G的数据加载到缓存中再传递,这是不可想象的。这个时候我们想到的就是断点续传。由于数据量很大。会导致当前程序阻塞,所以采用异步发送的方式,以进度条显示出来,这也是本篇文章所要实现的功能. 另外,目前BasicHttpBinding, NetTcpBinding, 和NetNamedPipeBinding 支持流处理模型,其他的不支持,这也影响stream的使用。
解释几个重要的概念以及实现的方式:
1、断点续传:就是在上一次下载/上传断开的位置开始继续下载/上传。微软已经提供好了这样的方法: BinaryWriter 这个是二进制的写入器,看下面:
{
public class BinaryWriter : IDisposable
{
public virtual long Seek(int offset, SeekOrigin origin); //设置当前流中的位置,第一个参数表示偏移量,第二个参数表示偏移量的参考依据
public virtual void Write(byte[] buffer); //把数据写入Seek方法设置的位置
}
}
2、异步线程:就是使用后台程序,不用阻塞当前线程,使用backgroundWorker组建,可以大大减少代码的编写量
下面的操作都是与WCF相关的部分。首先我们要定义一个数据契约用来传递数据:
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; }
}
接着定义操作的契约:
public interface IFilesLoad
{
[OperationContract]
List<FileInfo> GetFilesList(); //获得以已经上传的文件列表
[OperationContract]
FileInfo GetFiles(string fileName); //根据文件名寻找文件是否存在,返回文件的字节长度
[OperationContract]
FileInfo UplodaFile(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配置
<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特意为大文件提供的。下面看客户端代码:
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
wcf综合运用之:大文件异步断点续传的更多相关文章
- .net大文件传输断点续传源码
IE的自带下载功能中没有断点续传功能,要实现断点续传功能,需要用到HTTP协议中鲜为人知的几个响应头和请求头. 一. 两个必要响应头Accept-Ranges.ETag 客户端每次提交下载请求时,服务 ...
- 大文件视频断点续传插件resumabel.js,优化上传速度,缩短最后一片等待时长。
在angular中使用resumable.js遇到的一个问题:大视频上传到99-100%时,此时正在上传最后一片,最后一片的xhr一直是pending状态.原因插件会检查第一片和最后一片的元数据,检测 ...
- php大文件传输断点续传源码
1.使用PHP的创始人 Rasmus Lerdorf 写的APC扩展模块来实现(http://pecl.php.net/package/apc) APC实现方法: 安装APC,参照官方文档安装,可以使 ...
- mac下载百度云盘大文件及断点续传的方法
问题 作为资源共享平台, 百度云做的还是很出色的, "xxx site:pan.baidu.com"就可以找到很丰富的资源. 然而, 下载百度云上的文件就略蛋疼了. 早在12年的时 ...
- asp.net大文件传输断点续传源码
HTML部分 <%@PageLanguage="C#"AutoEventWireup="true"CodeBehind="index.aspx. ...
- jsp大文件传输断点续传源码
这里只写后端的代码,基本的思想就是,前端将文件分片,然后每次访问上传接口的时候,向后端传入参数:当前为第几块文件,和分片总数 下面直接贴代码吧,一些难懂的我大部分都加上注释了: 上传文件实体类: 看得 ...
- Mvc下异步断点续传大文件
最近公司一同事咨询了一个MVC项目下上传大文件时遇到的问题,问题描述如下: MVC项目中,当上传比较大的文件时,速度非常慢,小文件基本没有影响. 原因分析: 如果是用传统的form表单去提交的话,会将 ...
- 基于WCF的支持跨局域网可断点续传的大文件传输服务实现
题外话:这个系列的文章记录了本人最近写的一个小工程,主要包含了两个功能,一是对文件的断点续传的功能,二是基于WCF的一对多文件主动发送的功能,顺便这也是我自己在WCF学习路上的一个小成果吧. 在网上找 ...
- js解决大文件断点续传
最近遇见一个需要上传百兆大文件的需求,调研了七牛和腾讯云的切片分段上传功能,因此在此整理前端大文件上传相关功能的实现. 在某些业务中,大文件上传是一个比较重要的交互场景,如上传入库比较大的Excel表 ...
随机推荐
- docker端口映射设置
摘自 Docker学习笔记(3)-- 如何使用Dockerfile构建镜像 # 映射一个端口 EXPOSE port1 # 相应的运行容器使用的命令 docker run -p port1 image ...
- Mac 下 Chrome 快捷键大全
1. 标签页和窗口快捷键 ⌘-N 打开新窗口. ⌘-T 打开新标签页. ⌘-Shift-N 在隐身模式下打开新窗口. 按 ⌘-O,然后选择文件. 在 Chrome 浏览器中打开计算机中的文件. 按住 ...
- window.onload()与$(document).ready()区别
浏览器加载完DOM后,会通过javascript为DOM元素添加事件,在javascript中,通常使用window.onload()方法. 在jquery中,则使用$(document).ready ...
- Ubuntu Android Studio 无法通过起动器开启
问题: 1.可以通过终端开启 2.通过Android-Studio建立的Application无法启动, 提示 No JDK found. Please validate either STUDIO_ ...
- 移动并改变alpha
<script type="text/javascript">function obj(x){return document.getElementById(x);}va ...
- hdu 4681 string
字符串DP 题意:给你三个字符串a,b,c求字符串d的长度. 字符串d满足的要求:是a和b的公共子序列,c是它的子串. 定义dp1[i][j]表示a的第 i 位与b的第 j 位之前相同的子序列长度(包 ...
- MIT6.828 虚拟地址转化为物理地址——二级分页
这个分页,主要是在mit6.828的lab2的背景下来说的. Mit6.828 Lab2:http://pdos.csail.mit.edu/6.828/2014/labs/lab2/ lab2主要讲 ...
- PHP获取中文汉字首字母方法
function getFirstLetter($str){ $fchar = ord($str{0}); if($fchar >= ord("A") and $fchar ...
- 菜鸟学java开篇
从事it工作已有接近两年的时间了, 一直从事的是php的工作, 一直都想学java ,原因就不多说了, 毕竟优秀的php程序员,都会是一个其他方面的高手, 例如java ,并不是说java有多好,ph ...
- 管理node_modules
http://stackoverflow.com/questions/15225865/centralise-node-modules-in-project-with-subproject