用WCF做大文件手机qq上传到电脑的文件在哪里,应该搭配什么样的传输协议和配置

WCF实现的文件上传和下载
前段时间,用WCF做了一个小项目,其中涉及到文件的上传下载。出于复习巩固的目的,今天简单梳理了一下,整理出来,下面展示如何一步步实现一个上传下载的WCF服务。
1.首先新建一个名为FileService的WCF服务库项目,如下图:
2.将Service,IService重命名为FileService,IFileService,如下图:
3.打开IFileService.cs,定义两个方法,如下:
[ServiceContract]
public interface IFileService
//上传文件
[OperationContract]
bool UpLoadFile(Stream filestream);
//下载文件
[OperationContract]
Stream DownLoadFile(string downfile);
4.上面方法定义了输入参数和返回参数,但是实际项目中往往是不够的,我们需要增加其他参数,如文件名,文件大小之类。然而WCF中有限定,如下:
保留要进行流处理的数据的参数必须是方法中的唯一参数。 例如,如果要对输入消息进行流处理,则该操作必须正好具有一个输入参数。 同样,如果要对输出消息进行流处理,则该操作必须正好具有一个输出参数或一个返回值。
参数和返回值的类型中至少有一个必须是 ,
所以我们需要用契约特性包装一下参数,修改代码如下:
[ServiceContract]
public interface IFileService
//上传文件
[OperationContract]
UpFileResult UpLoadFile(UpFile filestream);
//下载文件
[OperationContract]
DownFileResult DownLoadFile(DownFile downfile);
[MessageContract]
public class DownFile
[MessageHeader]
public string FileName { }
[MessageContract]
public class UpFileResult
[MessageHeader]
public bool IsSuccess { }
[MessageHeader]
public string Message { }
[MessageContract]
public class UpFile
[MessageHeader]
public long FileSize { }
[MessageHeader]
public string FileName { }
[MessageBodyMember]
public Stream FileStream { }
[MessageContract]
public class DownFileResult
[MessageHeader]
public long
FileSize { }
[MessageHeader]
public bool IsSuccess { }
[MessageHeader]
public string Message { }
[MessageBodyMember]
public Stream FileStream { }
5.现在服务契约定义好了,接下来实现契约的接口。打开FileService.cs文件,编写代码,实现服务端的上传下载文件服务,代码如下:
public class FileService : IFileService
public UpFileResult UpLoadFile(UpFile filedata)
UpFileResult result = new UpFileResult();
string path = System.AppDomain.CurrentDomain.BaseDirectory +@"\service\";
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
byte[] buffer = new byte[filedata.FileSize];
FileStream fs = new FileStream(path + filedata.FileName, FileMode.Create, FileAccess.Write);
int count = 0;
while ((count = filedata.FileStream.Read(buffer, 0, buffer.Length)) & 0)
fs.Write(buffer, 0, count);
//清空缓冲区
fs.Flush();
fs.Close();
result.IsSuccess =
//下载文件
public DownFileResult DownLoadFile(DownFile filedata)
DownFileResult result = new DownFileResult();
string path = System.AppDomain.CurrentDomain.BaseDirectory + @"\service\" + filedata.FileN
if (!File.Exists(path))
result.IsSuccess =
result.FileSize = 0;
result.Message = "服务器不存在此文件";
result.FileStream = new MemoryStream();
Stream ms = new MemoryStream();
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
fs.CopyTo(ms);
ms.Position = 0;
//重要,不为0的话,客户端读取有问题
result.IsSuccess =
result.FileSize = ms.L
result.FileStream =
fs.Flush();
fs.Close();
6.至此,具体实现代码完成,但是我们还需要配置一下App.config,设置地址,契约和绑定。这里绑定采用NetTcpBinding,我们还需要为NetTcpBinding具体配置,如maxReceivedMessageSize(配置最大接收文件大小),transferMode(传输模式,这里是Streamed)等。最终代码如下:
&?xml version="1.0" encoding="utf-8" ?&
&configuration&
&appSettings&
&add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /&
&/appSettings&
&system.web&
&compilation debug="true" /&
&/system.web&
&!-- 部署服务库项目时,必须将配置文件的内容添加到
主机的 app.config 文件中。System.Configuration 不支持库的配置文件。--&
&system.serviceModel&
&bindings&
&netTcpBinding&
&binding name="MyTcpBinding" maxBufferSize="" maxReceivedMessageSize="" sendTimeout="00:30:00" transferMode="Streamed"
&security mode="None"&&/security&
&/binding&
&/netTcpBinding&
&/bindings&
&services&
&service name="WcfTest.FileService"&
&endpoint address="" binding="netTcpBinding" bindingConfiguration="MyTcpBinding" contract="WcfTest.IFileService"&
&identity&
&dns value="localhost" /&
&/identity&
&/endpoint&
&endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /&
&baseAddresses&
&add baseAddress="http://localhost:8733/Design_Time_Addresses/WcfTest/Service1/" /&
&add baseAddress="net.tcp://localhost:8734/Design_Time_Addresses/WcfTest/Service1/" /&
&/baseAddresses&
&/service&
&/services&
&behaviors&
&serviceBehaviors&
&behavior&
&!-- 为避免泄漏元数据信息,
请在部署前将以下值设置为 false --&
&serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/&
&!-- 要接收故障异常详细信息以进行调试,
请将以下值设置为 true。在部署前设置为 false
以避免泄漏异常信息--&
&serviceDebug includeExceptionDetailInFaults="False" /&
&/behavior&
&/serviceBehaviors&
&/behaviors&
&/system.serviceModel&
&/configuration&
7.这时可以运行服务,如果没有问题的话,会看到如下截图。
1.首先新建一个WPF应用程序,在MainWindow.xaml添加,得到下图:
2.在引用中右击,选择添加服务引用,出现对话框,我们需要填上刚才打开的服务的地址,然后按旁边的转到,会看到显示找到服务,接着更改命名空间为FileService,得到如下图。
2.按确定之后,在资源管理器里的引用下面会多出一个FileService命名空间,里面包含我们的刚才写的FileServiceClient服务代理类 ,现在我们可以通过它调用服务了。编写代码如下:
public partial class MainWindow : Window
FileServiceC
public MainWindow()
InitializeComponent();
client = new FileServiceClient();
private void Button_Click_1(object sender, RoutedEventArgs e)
OpenFileDialog Fdialog = new OpenFileDialog();
if (Fdialog.ShowDialog().Value)
using (Stream fs = new FileStream(Fdialog.FileName, FileMode.Open, FileAccess.Read))
this.filepath.Text = Fdialog.SafeFileN
bool result = client.UpLoadFile(Fdialog.SafeFileName, fs.Length,fs, out message);
if (result == true)
MessageBox.Show("上传成功!");
MessageBox.Show(message);
private void Button_Click_2(object sender, RoutedEventArgs e)
string filename = this.filename.T
string path = System.AppDomain.CurrentDomain.BaseDirectory + @"\client\";
bool issuccess=
string message="";
Stream filestream=new MemoryStream();
long filesize = client.DownLoadFile(filename, out issuccess, out message, out filestream);
if (issuccess)
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
byte[] buffer = new byte[filesize];
FileStream fs = new FileStream(path + filename, FileMode.Create, FileAccess.Write);
int count = 0;
while ((count = filestream.Read(buffer, 0, buffer.Length)) & 0)
fs.Write(buffer, 0, count);
//清空缓冲区
fs.Flush();
fs.Close();
MessageBox.Show("下载成功!");
MessageBox.Show(message);
3.运行程序,上传下载文件,会在和客服端运行目录下分别找到上传的文件和下载的文件,测试通过。界面如下:
本文通过图文一步步介绍了如何实现上传下载文件功能,其中涉及到WCF知识点其实是不少的,但是都是简单地带过。如果有不明白的地方,可以查阅Google,百度,也可以留言。如果您有更好的建议,请不吝指教,感激不尽!
没有更多推荐了,此篇文章主要是基于http协议应用于大文件传输中的应用,现在我们先解析下wcf中编码器的定义,编码器实现了类的编码,并负责将Message内存中消息转变为网络发送的字节流或者字节缓冲区(对于发送方而言)。在接收方,编码会将一系列字节转变为内存中的消息
在wcf中有三个编码器
1、TextMessageEncodingBindingElement
&&&&&& 文本消息编码器是所有的基于Http的绑定的默认编码器,并且是最关注互操作性的所有的自定义绑定的正确选择。即为请求/应答模式,此编码器读取和编码标准为SOAP1.1/SOAP1.2的文本消息,而不会对二进制数据进行任何特殊处理,如果消息的MessageVersion设置为None,则SOAP信封包装从输出中省略,只有正文内容进行序列化。
2、MtomMessageEncodingBindingElement
&&&&& MTOM消息编码器是也是一个文本编码器,实现对二进制数据的特殊处理,默认情况下在任何标准绑定中都不会使用,也就是说需要我们自己定义(一般定义在wsHttpBinding中),因为它是一个严格按具体情况进行优化的实用工具,只有当二进制数据的量不超过某个阀值时,MTOM编码才具有优势,如果信息包含的二进制数据超过某个阀值,则这些数据会外部化消息信封之后的MIME部分
3、BinaryMessageEncodingBindingElement
&&&& 二进制消息编码器是Net*绑定的默认编码器,当通信双方都基于WCF时,此编码器始终是正确的选择。二进制消息编码使用.NET二进制XML格式,该格式是XML信息集(Information Sets,Infosets)的Microsoft特定二进制表示法,与等效的xml1.0表示法相比产生的需求量通常较小,并将二进制数据编码为字节流
每个标准绑定都包括一个预配置编码器,因此默认情况下Net*前缀的绑定使用二进制编码(通过包括BinaryMessageEncodingBindingElement类),而BasicHttpBinding和WSHttpBing类则使用文本信息编码器(通过TextMessageEncodingBindingElement类)
通常,文本信息编码是要求互操作性的任意通信路径的最佳选择,也就是通用性比较高,而二进制消息编码则是其他任意通信路径的最佳选择。通常,对于当个消息而言,二进制编码生成的消息要小于文本编码,并且在通信会话期间消息大小会逐渐变得更小。于文本编码不同的是,二进制编码不需要对数据进行特殊处理(例如,使用Base64),当会字节表示为字节
如果数据无法分段,消息必须及时的方式传递或者当传输启动时数据为完全就绪,则应考虑启用流模式,而且只能对大型消息(带文本或者二进制)启用流模式
&& 无法执行信息正文的数字签名,因为他们需要整个消息内容进行哈希算法。采用流模式的情况下,当构造和发送消息头时,内容尚未完全就绪,因此无法计算数字签名。
&& &加密依赖于数字签名验证是否已经正确的重新构造数据
&&& 如果消息在传输过程中丢失,可靠的会话必须在客户端上缓冲已发送的消息以便可以重新传递,并且在将消息传递给服务实现之前必须在服务上保留信息以保证信息顺序。以备在未按顺序接受消息时可以按照正确的顺寻重新排列消息
下面我们通过一个上传文件的简单程序实现流文件的上传:
有几点我们需要注意:
1、在我们流文件上传的时候,需要定义文件的一些属性,这样我们就需要用消息契约代替数据契约方式
2、流文件上传的时候我们定义方法的时候只能保持一个参数,即消息契约。
第一步、新建文件消息契约
using System.Collections.G
using System.ServiceM
using System.IO;
namespace streamFileUp
/// &summary&
/// 消息契约(定义与SOAP消息相对应的强类型)
/// 因为我们用流传输,所以用消息契约代替传统的数据契约
/// &/summary&
[MessageContract]
public class FileWrapper
/// &summary&
///SOAP的消息头这里即为标记文件的路径
/// &/summary&
[MessageHeader]
public string FileP
/// &summary&
/// SOAP消息的内容,指定成员序列化正文中的元素
/// &/summary&
[MessageBodyMember]
public Stream FileD
/// &summary&
/// 返回结果
/// &/summary&
[MessageContract]
public class result
[MessageBodyMember]
public bool
第二步,定义服务契约
using System.ServiceM
namespace streamFileUp
[ServiceContract]
public interface IStreamed
/// &summary&
/// 上传文件
/// &/summary&
/// 1、支持数据流传输的绑定有:BasicHttpBding、NetTcpBinding和NetNamedPipeBinding
/// 2、数据流类型必须是可序列化的sream或MemorySream
/// 3、传递时消息体(Message Body)中不可能包含其他数据,即参数只能有一个streamFileUp.FileWrapper
/// &param name="fileWrapper"&信息载体&/param&
[OperationContract]
result UploadFile(FileWrapper fileWrapper);
第三步、实现类,注释很全,就不解释了
using System.Collections.G
using System.IO;
using System.ServiceM
namespace streamFileUp
public class Streamed : IStreamed
/// &summary&
/// 上传文件
/// &/summary&
/// &param name="fileWrapper"&streamFileUp.FileWrapper&/param&
public result UploadFile(FileWrapper fileWrapper)
var sourceSream = fileWrapper.FileD
var targetSream = new FileStream(fileWrapper.FilePath,
FileMode.Create,
FileAccess.Write,
FileShare.None);
var buffer = new byte[4096];
var count = 0;
while ((count = sourceSream.Read(buffer, 0, buffer.Length)) & 0)
targetSream.Write(buffer, 0, count);
targetSream.Close();
sourceSream.Close();
catch (Exception)
return new result { returnresult = false };
return new result { returnresult = true };
第四步、我们采取自托管,新建服务
using System.ServiceM
namespace streamFileUp
class Program
static void Main(string[] args)
using (ServiceHost host = new ServiceHost(typeof(Streamed)))
host.Opened += delegate
Console.WriteLine("服务已经启动");
host.Open();
foreach (var endpoint in host.Description.Endpoints)
Console.WriteLine(endpoint.Address.ToString());
Console.ReadLine();
第五步,这里是我们的配置文件,晒一下,注释很详细,记住是配置流传输
&?xml version="1.0"?&
&configuration&
&supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/&
&/startup&
&system.serviceModel&
&services&
&!--name 提供服务的类名--&
&!--behaviorConfiguraron 指定相关的行为配置 --&
&service name="streamFileUp.Streamed"
behaviorConfiguration="MessageBehavior"&
&!--address - 服务地址--&
&!--binding - 通信方式--&
&!--contract - 服务契约--&
&!--bindingConfiguration - 指定相关的绑定配置--&
address="Message/Streamed"
binding="netTcpBinding"
contract="streamFileUp.IStreamed"
bindingConfiguration="StreamedBindingConfiguration" /&
&endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /&
&baseAddresses&
&add baseAddress="http://localhost:12345/Message/Streamed/"/&
&add baseAddress="net.tcp://localhost:54321/"/&
&/baseAddresses&
&/service&
&/services&
&behaviors&
&serviceBehaviors&
&behavior name="MessageBehavior"&
&!--httpGetEnabled - 使用get方式提供服务--&
&serviceMetadata httpGetEnabled="true" /&
&serviceDebug includeExceptionDetailInFaults="true"/&
&/behavior&
&/serviceBehaviors&
&/behaviors&
&bindings&
&netTcpBinding&
&!--transferMode - 指示通道是使用流处理模式还是缓冲模式来传输请求和响应消息--&
&!--maxReceivedMessageSize - 在采用此绑定配置的通道上可接收的最大消息大小(单位:字节)--&
&!--receiveTimeout - 在传输引发异常之前可用于完成读取操作的时间间隔--&
name="StreamedBindingConfiguration"
transferMode="Streamed"
maxReceivedMessageSize=""
receiveTimeout="00:10:00" /&
&/netTcpBinding&
&/bindings&
&/system.serviceModel&
&/configuration&
到此我们的服务端已经建立成功了,跑一下试试...
可以看到我们公开了两个服务地址,一个是net.tcp、一个是http...其实这里面http地址是引用服务的基地址,其传递方式还是采用
tcp方式的,一会我们通过客户端验证来下我们的推测。
下面我们开始新建客户端,来连接该服务:
第一步、新建类库,引用该服务,这里面有几点注意,在流的传输下我们客户端生成代码的时候服务地址是不能用上面的net.tcp...
我们需要引用http:......基地址生成:
第三步、实现客户端上传文件:
using System.Collections.G
using System.ServiceM
namespace client
class Program
static void Main(string[] args)
///自定义绑定
string strAddress = "net.tcp://localhost:54321/Message/Streamed";
ChannelFactory&ServiceFileUp.IStreamed& factory = new ChannelFactory&ServiceFileUp.IStreamed&("NetTcpBinding_IStreamed", new EndpointAddress(strAddress));
ServiceFileUp.IStreamed service = factory.CreateChannel();
string filePath = @"G:\wcf学习测试案例\wcf大型数据传输\1.jpg";
string newFilePath = @"G:\wcf学习测试案例\wcf大型数据传输\2.jpg";
System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); //定义观察者
watch.Start();
ServiceFileUp.result returnResult = service.UploadFile(getSreamFromFile(filePath, newFilePath));
watch.Stop();
if (returnResult.returnresult)
Console.WriteLine("上传成功,上传时间为:" + watch.ElapsedMilliseconds);
Console.ReadLine();
Console.WriteLine("上传失败");
Console.ReadLine();
/// &summary&
/// 流数据上传文件
/// &/summary&
/// &param name="file"&源文件地址&/param&
public static ServiceFileUp.FileWrapper getSreamFromFile(string file, string newFilePath)
ServiceFileUp.FileWrapper myFileFw = null;
var sr = new System.IO.FileStream(
file, System.IO.FileMode.Open);
ServiceFileUp.FileWrapper oneFW = new ServiceFileUp.FileWrapper()
FilePath = newFilePath,
FileData = sr
myFileFw = oneFW;
Console.WriteLine("文件大小为:"+sr.Length.ToString());
//sr.Close();
catch (Exception ex)
Console.WriteLine(ex.ToString());
return myFileFw;
我们在G盘下面放了一个jpg文件,然后通过上传同样的在该目录下存入我们刚才上传的文件,这里我们顺便监听了一下上传该文件需要的时间
下面晒一下结果:
说明文件上传是成功的,下面我们变换一种方式,以上方式我们是自定义了net.tcp地址的方式实现了文件的上传,我们改变一下直接用
http方式看看文件上传时候会变慢:
看运行结果:
呵呵...同样能实现上传的功能,但是性能的落后于基地址赋值地址,当然本身client方式就是通过ChannelFactory工厂创建,性能有所耗损是必然的,这里同样告诫我们:
在大文件传输的时候我们最好是通过自定义地址实现客户端配置,当然我们现在只是传递了一个简单的图片,对于大文件的上传我们需要更多的配置和性能优化。
阅读(...) 评论()基于TCP协议的WCF传输大文件怎么出现进度条_百度知道
基于TCP协议的WCF传输大文件怎么出现进度条
我有更好的答案
基于TCP协议的WCF传输大文件如何出现进度条RT.比如传输50M的文件,我能显示个进度条 2000Kb of 5000Kb 已传输40%.有回复了加分.------解决方案--------------------不建议用WCF做文件传输参考以下代码(VS2008下测试通过)Service端:C# codeusing Susing System.Collections.Gusing System.Lusing System.Tusing System.ServiceMusing System.IO;using System.ServiceModel.Dusing System.ServiceModel.Dusing System.ServiceModel.Cnamespace FSDownloadService{
[MessageContract]
public class MyFileInfo
[MessageHeader]
public string FileN
[MessageHeader]
public long FileS
[MessageBodyMember]
public Stream S
public MyFileInfo() { }
public MyFileInfo(Stream stream, string fileName, long fileSize)
this.Stream =
this.FileSize = fileS
this.FileName = fileN
[MessageContract]
public class DownloadFileRequest
[MessageBodyMember]
public readonly string FileN
public DownloadFileRequest() { }
public DownloadFileRequest(string fileName)
this.FileName = fileN
[ServiceContract]
public interface IFileManager
[OperationContract]
MyFileInfo DownloadFile(DownloadFileRequest request);
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class MyService : IFileManager
public MyFileInfo DownloadFile(DownloadFileRequest request)
FileInfo fi = new FileInfo(request.FileName);
MyFileInfo result = new MyFileInfo(File.OpenRead(request.FileName), request.FileName, fi.Length);
public class MyHost
static ServiceHost host =
public static void Open()
string baseAddress = &net.tcp://localhost:2008/FileService&;
host = new ServiceHost(typeof(MyService), new Uri(baseAddress));
host.AddServiceEndpoint(typeof(IFileManager), GetTcpBinding(), &&);
host.Open();
public static void Close()
if (host != null && host.State == CommunicationState.Opened)
host.Close();
public static Binding GetTcpBinding()
NetTcpBinding binding = new NetTcpBinding();
binding.TransferMode = TransferMode.S
binding.MaxReceivedMessageSize = int.MaxV
采纳率:94%
来自团队:
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。WCF下上传大文件错误~ 求解
[问题点数:20分,结帖人chentank]
本版专家分:0
结帖率 99.16%
CSDN今日推荐
本版专家分:23079
本版专家分:0
本版专家分:23079
本版专家分:55078
本版专家分:0
本版专家分:0
本版专家分:0
匿名用户不能发表回复!|
其他相关推荐
在使用Socket/TCP来传输文件,弄起来不仅会有些复杂,而且较经典的“粘包”问题有时候会让人火冒七丈。如果你不喜欢用Socket来传文件,不妨试试WCF,WCF的流模式传输还是相当强大和相当实用的。
因为开启流模式是基于绑定的,所以,它会影响到整个终结点的操作协定。如果你不记得或者说不喜欢背书,不想去记住哪些绑定支持流模式,可以通过以下方法:
因为开启流模式,主要是设置一个叫Transfe
using System.Collections.G
using System.L
using System.W
using System.ServiceM
using System.IO;
using System.ServiceModel.W
namespace EFTest.Te
0x00 框架本身文件大小限制框架JS文件方法一:配置参数(推荐)&link rel=&stylesheet& href=&kindeditor/themes/default/default.css& /&
&script charset=&utf-8& src=&kindeditor/kindeditor-all.js&&&/script&
&script charset=&utf-8& src=
wcf上传文件的范例,可以上传大文件,还提供断点续传的功能。
WCF中的流传输实现文件分段传输
  WCF默认是缓存传输模式,但是这样会占用服务器宝贵的内存资源,连接数越多,占用的内存就越多,当传输大数据特别是大文件的时候,内存会消耗光。有人给出过WCF下大数据传输方案,不过那还是在缓存模式下的,而且不方便管理,无法实际使用。
  显然,使用流传输模式可以解决上述问题。不过流也有些不便之处,首先是不支持会话,它只能在PerCall的模式下工作,用户验证信
WCF大文件断点下载示例
完整项目下载:http://files.cnblogs.com/qldsrx/FilesManager.rar
  之前发过片段的内容,都没给出完整的项目代码,不少人来要,故整理下,做个完整的演示项目出来,花了4天的时间调试,真要命。另外如果是IIS承载的WCF服务,建议直接写一个继承IHttpHandler的类来实现,那样效率更高,控制更精细,用WCF服务来做仅仅是在
wcf rest主要是走路由来开发的API,配置路由:
接口方法类:
可GET post put 等 其他一般用不到
多文件上传文件流代码:
/// 遍历循环 附件上传文件方法
exception 'yii\web\BadRequestHttpException' with message 'Unable to verify your data submission.' in /var/www/html/labweb/vendor/yiisoft/yii2/web/Controller.php:110
Stack trace:
#0 /var/www/html/lab
采用了WCF技术,多线程上传大文件到服务器
WCF文件下载上传源码以及测试服务源码,已更改WCF服务配额}

我要回帖

更多关于 qq文件个数达到上限 无法上传 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信