项目包含一个 WCF 服务器, 以及一个 Winform 客户端,客户端通过硬编码实现 Binding 调用

项目包含一个 WCF 服务器, 以及一个 Winform 客户端,客户端通过硬编码实现 Binding 调用

源码点击这里查看

1. 添加 WCF service UpLoadService,修改接口文件 IUpLoadService如下

[ServiceContract]
    public interface IUpLoadService
    {
        [OperationContract(Action = "UploadFile", IsOneWay = true)]
        void UploadFile(FileUploadMessage request);
    <span class="token punctuation">[</span><span class="token function">OperationContract</span><span class="token punctuation">(</span>Action <span class="token operator">=</span> <span class="token string">"DownLoadFile"</span><span class="token punctuation">)</span><span class="token punctuation">]</span>
    DownFileResult <span class="token function">DownLoadFile</span><span class="token punctuation">(</span>DownFileRequest fileName<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

其中,request model 和 result model 定义如下:

   [MessageContract]
    public class FileUploadMessage
    {
        [MessageHeader(MustUnderstand = true)]
        public string SavePath;
    <span class="token punctuation">[</span><span class="token function">MessageHeader</span><span class="token punctuation">(</span>MustUnderstand <span class="token operator">=</span> true<span class="token punctuation">)</span><span class="token punctuation">]</span>
    public string FileName<span class="token punctuation">;</span>

    <span class="token punctuation">[</span><span class="token function">MessageBodyMember</span><span class="token punctuation">(</span>Order <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">]</span>
    public Stream FileData<span class="token punctuation">;</span>

<span class="token punctuation">}</span>

<span class="token punctuation">[</span>MessageContract<span class="token punctuation">]</span>
public class DownFileRequest
<span class="token punctuation">{</span>
    <span class="token punctuation">[</span>MessageHeader<span class="token punctuation">]</span>
    public string FileName <span class="token punctuation">{</span> get<span class="token punctuation">;</span> set<span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token punctuation">[</span>MessageContract<span class="token punctuation">]</span>
public class DownFileResult
<span class="token punctuation">{</span>
    <span class="token punctuation">[</span>MessageHeader<span class="token punctuation">]</span>
    public <span class="token keyword">long</span> FileSize <span class="token punctuation">{</span> get<span class="token punctuation">;</span> set<span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <span class="token punctuation">[</span>MessageHeader<span class="token punctuation">]</span>
    public bool IsSuccess <span class="token punctuation">{</span> get<span class="token punctuation">;</span> set<span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <span class="token punctuation">[</span>MessageHeader<span class="token punctuation">]</span>
    public string Message <span class="token punctuation">{</span> get<span class="token punctuation">;</span> set<span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <span class="token punctuation">[</span>MessageBodyMember<span class="token punctuation">]</span>
    public Stream FileStream <span class="token punctuation">{</span> get<span class="token punctuation">;</span> set<span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

  • DownLoadFile 的入参仅有一个 fileName 参数,之所以要定义一个类存放,是因为 WCF 的限制:流式传递时消息体(Message Body)中不能包含其他数据。所以传入参数和传出参数都要分别定义自己的类型
  • OperationContract 的属性 IsOneWay 设为 true 时,入参和出参只能存在一个

2. 修改实现类 UpLoadService 如下

    public class UpLoadService : IUpLoadService
    {
        // my project is based on net 3.5. if not ,you can use Stream.CopyTo() method
        public static void CopyTo(Stream input, Stream output)
        {
            byte[] buffer = new byte[16 * 1024]; // Fairly arbitrary size
            int bytesRead;
        <span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>bytesRead <span class="token operator">=</span> input<span class="token punctuation">.</span><span class="token function">Read</span><span class="token punctuation">(</span>buffer<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> buffer<span class="token punctuation">.</span>Length<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">&gt;</span> <span class="token number">0</span><span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            output<span class="token punctuation">.</span><span class="token function">Write</span><span class="token punctuation">(</span>buffer<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> bytesRead<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    public DownFileResult <span class="token function">DownLoadFile</span><span class="token punctuation">(</span>DownFileRequest fileRequest<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        DownFileResult msg <span class="token operator">=</span> new <span class="token function">DownFileResult</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        string fileName <span class="token operator">=</span> fileRequest<span class="token punctuation">.</span>FileName<span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>File<span class="token punctuation">.</span><span class="token function">Exists</span><span class="token punctuation">(</span>fileName<span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            msg<span class="token punctuation">.</span>IsSuccess <span class="token operator">=</span> false<span class="token punctuation">;</span>
            msg<span class="token punctuation">.</span>FileSize <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
            msg<span class="token punctuation">.</span>Message <span class="token operator">=</span> <span class="token string">"服务器不存在此文件"</span><span class="token punctuation">;</span>
            msg<span class="token punctuation">.</span>FileStream <span class="token operator">=</span> new <span class="token function">MemoryStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span> msg<span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        Stream ms <span class="token operator">=</span> new <span class="token function">MemoryStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        FileStream fs <span class="token operator">=</span> new <span class="token function">FileStream</span><span class="token punctuation">(</span>fileName<span class="token punctuation">,</span> FileMode<span class="token punctuation">.</span>Open<span class="token punctuation">,</span> FileAccess<span class="token punctuation">.</span>Read<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">CopyTo</span><span class="token punctuation">(</span>fs<span class="token punctuation">,</span> ms<span class="token punctuation">)</span><span class="token punctuation">;</span>
        ms<span class="token punctuation">.</span>Position <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>  <span class="token comment">//重要,不为0的话,客户端读取有问题</span>
        
        msg<span class="token punctuation">.</span>IsSuccess <span class="token operator">=</span> true<span class="token punctuation">;</span>
        msg<span class="token punctuation">.</span>FileSize <span class="token operator">=</span> ms<span class="token punctuation">.</span>Length<span class="token punctuation">;</span>
        msg<span class="token punctuation">.</span>FileStream <span class="token operator">=</span> ms<span class="token punctuation">;</span>
        fs<span class="token punctuation">.</span><span class="token function">Flush</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        fs<span class="token punctuation">.</span><span class="token function">Close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> msg<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    public <span class="token keyword">void</span> <span class="token function">UploadFile</span><span class="token punctuation">(</span>FileUploadMessage request<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        string fileName <span class="token operator">=</span> request<span class="token punctuation">.</span>FileName<span class="token punctuation">;</span>
        Stream sourceStream <span class="token operator">=</span> request<span class="token punctuation">.</span>FileData<span class="token punctuation">;</span>
        FileStream targetStream <span class="token operator">=</span> null<span class="token punctuation">;</span>

        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>sourceStream<span class="token punctuation">.</span>CanRead<span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            throw new <span class="token function">Exception</span><span class="token punctuation">(</span><span class="token string">"数据流不可读!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        string uploadFolder <span class="token operator">=</span> System<span class="token punctuation">.</span>Web<span class="token punctuation">.</span>Hosting<span class="token punctuation">.</span>HostingEnvironment<span class="token punctuation">.</span>ApplicationPhysicalPath<span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>Directory<span class="token punctuation">.</span><span class="token function">Exists</span><span class="token punctuation">(</span>uploadFolder<span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            Directory<span class="token punctuation">.</span><span class="token function">CreateDirectory</span><span class="token punctuation">(</span>uploadFolder<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        string filePath <span class="token operator">=</span> Path<span class="token punctuation">.</span><span class="token function">Combine</span><span class="token punctuation">(</span>uploadFolder<span class="token punctuation">,</span> fileName<span class="token punctuation">)</span><span class="token punctuation">;</span>
        using <span class="token punctuation">(</span>targetStream <span class="token operator">=</span> new <span class="token function">FileStream</span><span class="token punctuation">(</span>filePath<span class="token punctuation">,</span> FileMode<span class="token punctuation">.</span>Create<span class="token punctuation">,</span> FileAccess<span class="token punctuation">.</span>Write<span class="token punctuation">,</span> FileShare<span class="token punctuation">.</span>None<span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token comment">//read from the input stream in 4K chunks</span>
            <span class="token comment">//and save to output stream</span>
            <span class="token keyword">const</span> <span class="token keyword">int</span> bufferLen <span class="token operator">=</span> <span class="token number">4096</span><span class="token punctuation">;</span>
            byte<span class="token punctuation">[</span><span class="token punctuation">]</span> buffer <span class="token operator">=</span> new byte<span class="token punctuation">[</span>bufferLen<span class="token punctuation">]</span><span class="token punctuation">;</span>
            <span class="token keyword">int</span> count <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
            <span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>count <span class="token operator">=</span> sourceStream<span class="token punctuation">.</span><span class="token function">Read</span><span class="token punctuation">(</span>buffer<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> bufferLen<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">&gt;</span> <span class="token number">0</span><span class="token punctuation">)</span>
            <span class="token punctuation">{</span>
                targetStream<span class="token punctuation">.</span><span class="token function">Write</span><span class="token punctuation">(</span>buffer<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> count<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
            targetStream<span class="token punctuation">.</span><span class="token function">Close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            sourceStream<span class="token punctuation">.</span><span class="token function">Close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

3. 接下来是重点,需要配置 Web.config 文件支持流式传输大文件

  • system.web 节点下添加配置
<system.web>
    // 指定输入流缓冲阈值的限制,单位为 KB
    <httpRuntime maxRequestLength="2147483647" />
    // 其他的系统配置,比如 authentication 等
</system.web>
  • bindings 下新增配置
    <bindings>
      <basicHttpBinding>
        <binding name="FileTransferServicesBinding" maxReceivedMessageSize="9223372036854775807"
          messageEncoding="Mtom" transferMode="Streamed" sendTimeout="00:10:00" />
      </basicHttpBinding>
    </bindings>
  • service 配置改为如下
      <service behaviorConfiguration="WcfFileUploadService.UpLoadServiceBehavior" name="WcfFileUploadService.UpLoadService">
          <endpoint address="" binding="basicHttpBinding" bindingConfiguration="FileTransferServicesBinding" contract="WcfFileUploadService.IUpLoadService">
          </endpoint>
          <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>

4. 编写客户端代码,添加 service 引用,输入 running 的 wcf 地址,导入相关调用文件

  • 修改客户端 app.config 文件(与服务器配置一致)
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="FileTransferServicesBinding" maxReceivedMessageSize="9223372036854775807"
                 messageEncoding="Mtom" transferMode="Streamed" sendTimeout="00:10:00" />
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost:62805/UpLoadService.svc"
                binding="basicHttpBinding" bindingConfiguration="FileTransferServicesBinding"
                contract="ServiceReference1.IUpLoadService" name="BasicHttpBinding_IUpLoadService" />
    </client>
  </system.serviceModel>
</configuration>
  • 上传调用代码示例
    (1) 使用 app.config 配置
            FileStream stream = File.OpenRead(fileName);
            IUpLoadService service = new UpLoadServiceClient();
            var req = new FileUploadMessage(fileName.Substring(0, fileName.LastIndexOf('.')), "", stream);
            service.UploadFile(req);
            stream.Close();

(2) 手动创建 binding

            FileStream stream = File.OpenRead(fileName);
            var req = new FileUploadMessage(fileName.Substring(fileName.LastIndexOf('\\')+1), "", stream);
        BasicHttpBinding binding <span class="token operator">=</span> new <span class="token function">BasicHttpBinding</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        binding<span class="token punctuation">.</span>TransferMode <span class="token operator">=</span> TransferMode<span class="token punctuation">.</span>Streamed<span class="token punctuation">;</span>
        binding<span class="token punctuation">.</span>SendTimeout <span class="token operator">=</span> new <span class="token function">TimeSpan</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token number">10</span><span class="token punctuation">,</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 设置十分钟超时</span>
        binding<span class="token punctuation">.</span>MessageEncoding <span class="token operator">=</span> WSMessageEncoding<span class="token punctuation">.</span>Mtom<span class="token punctuation">;</span>
        binding<span class="token punctuation">.</span>MaxReceivedMessageSize <span class="token operator">=</span> <span class="token number">9223372036854775807</span><span class="token punctuation">;</span>

        IUpLoadService channel <span class="token operator">=</span> ChannelFactory<span class="token operator">&lt;</span>IUpLoadService<span class="token operator">&gt;</span><span class="token punctuation">.</span><span class="token function">CreateChannel</span><span class="token punctuation">(</span>binding<span class="token punctuation">,</span>
            new <span class="token function">EndpointAddress</span><span class="token punctuation">(</span><span class="token string">"http://localhost:62805/UpLoadService.svc"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        using <span class="token punctuation">(</span>channel as IDisposable<span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            channel<span class="token punctuation">.</span><span class="token function">UploadFile</span><span class="token punctuation">(</span>req<span class="token punctuation">)</span><span class="token punctuation">;</span>
            stream<span class="token punctuation">.</span><span class="token function">Close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            this<span class="token punctuation">.</span>Cursor <span class="token operator">=</span> Cursors<span class="token punctuation">.</span>Default<span class="token punctuation">;</span>
            MessageBox<span class="token punctuation">.</span><span class="token function">Show</span><span class="token punctuation">(</span><span class="token string">"文件上传到服务器成功"</span><span class="token punctuation">,</span> <span class="token string">"上传WCF"</span><span class="token punctuation">,</span> MessageBoxButtons<span class="token punctuation">.</span>OK<span class="token punctuation">,</span> MessageBoxIcon<span class="token punctuation">.</span>Information<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

  • 下载调用代码示例
    (1) 使用 app.config 配置
            DownFileRequest req = new DownFileRequest(fileName);
            IUpLoadService svc = new UpLoadServiceClient();
            var res = svc.DownLoadFile(req);
            if (res.IsSuccess)
            {
                using (var fileStream = File.Create(AppDomain.CurrentDomain.BaseDirectory+"\\"+fileName.Substring(fileName.LastIndexOf('\\')+1)) )
                {
                    CopyTo(res.FileStream, fileStream);
                }
            }

(2) 手动创建 binding

            DownFileRequest req = new DownFileRequest(fileName);
            BasicHttpBinding binding = new BasicHttpBinding();
            binding.TransferMode = TransferMode.Streamed;
            binding.MessageEncoding = WSMessageEncoding.Mtom;
            binding.MaxReceivedMessageSize = 9223372036854775807;
        IUpLoadService channel <span class="token operator">=</span> ChannelFactory<span class="token operator">&lt;</span>IUpLoadService<span class="token operator">&gt;</span><span class="token punctuation">.</span><span class="token function">CreateChannel</span><span class="token punctuation">(</span>binding<span class="token punctuation">,</span>
            new <span class="token function">EndpointAddress</span><span class="token punctuation">(</span><span class="token string">"http://localhost:62805/UpLoadService.svc"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        using <span class="token punctuation">(</span>channel as IDisposable<span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            var res <span class="token operator">=</span> channel<span class="token punctuation">.</span><span class="token function">DownLoadFile</span><span class="token punctuation">(</span>req<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>res<span class="token punctuation">.</span>IsSuccess<span class="token punctuation">)</span>
            <span class="token punctuation">{</span>
                using <span class="token punctuation">(</span>var fileStream <span class="token operator">=</span> File<span class="token punctuation">.</span><span class="token function">Create</span><span class="token punctuation">(</span>AppDomain<span class="token punctuation">.</span>CurrentDomain<span class="token punctuation">.</span>BaseDirectory <span class="token operator">+</span> <span class="token string">"\\"</span> <span class="token operator">+</span> fileName<span class="token punctuation">.</span><span class="token function">Substring</span><span class="token punctuation">(</span>fileName<span class="token punctuation">.</span><span class="token function">LastIndexOf</span><span class="token punctuation">(</span><span class="token string">'\\'</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token punctuation">{</span>
                    <span class="token function">CopyTo</span><span class="token punctuation">(</span>res<span class="token punctuation">.</span>FileStream<span class="token punctuation">,</span> fileStream<span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token punctuation">}</span>
            <span class="token punctuation">}</span>
            this<span class="token punctuation">.</span>Cursor <span class="token operator">=</span> Cursors<span class="token punctuation">.</span>Default<span class="token punctuation">;</span>
            MessageBox<span class="token punctuation">.</span><span class="token function">Show</span><span class="token punctuation">(</span>res<span class="token punctuation">.</span>IsSuccess <span class="token operator">?</span> <span class="token string">"文件下载成功!"</span> <span class="token operator">:</span> res<span class="token punctuation">.</span>Message<span class="token punctuation">,</span> <span class="token string">"上传文件测试"</span><span class="token punctuation">,</span> MessageBoxButtons<span class="token punctuation">.</span>OK<span class="token punctuation">,</span>
                res<span class="token punctuation">.</span>IsSuccess <span class="token operator">?</span> MessageBoxIcon<span class="token punctuation">.</span>Information <span class="token operator">:</span> MessageBoxIcon<span class="token punctuation">.</span>Error<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值