使用WCF上传文件

 
        在WCF没出现之前,我一直使用用WebService来上传文件,我不知道别人为什么要这么做,因为我们的文件服务器和网站后台和网站前台都不在同一个机器,操作人员觉得用FTP传文件太麻烦,我就做一个专门用来上传文件的WebService,把这个WebService部署在文件服务器上,然后在网站后台调用这个WebService,把网站后台页面上传上来的文件转化为字节流传给WebService,然后WebService把这个字节流保存文件到一个只允许静态页面的网站(静态网站可以防止一些脚本木马)。 WebService来上传文件存在的问题是效率不高,而且不能传输大数据量的文件,当然你可以用Wse中的MTOM来传输大文件,有了WCF就好多了,通过使用WCF传递Stream对象来传递大数据文件,但有一些限制:

1、只有 BasicHttpBinding、NetTcpBinding 和 NetNamedPipeBinding 支持传送流数据。

2、 流数据类型必须是可序列化的 Stream 或 MemoryStream。

3、 传递时消息体(Message Body)中不能包含其他数据。

4、TransferMode的限制和MaxReceivedMessageSize的限制等。

下面具体实现:新建一个WCFService,接口文件的代码如下:

{
        [OperationContract(Action = "UploadFile", IsOneWay = true)]
        void UploadFile(FileUploadMessage request);
    }


    [MessageContract]
    public class FileUploadMessage
    {
        [MessageHeader(MustUnderstand = true)]
        public string SavePath;

        [MessageHeader(MustUnderstand = true)]
        public string FileName;

        [MessageBodyMember(Order = 1)]
        public Stream FileData;

    }{
        [OperationContract(Action = "UploadFile", IsOneWay = true)]
        void UploadFile(FileUploadMessage request);
    }

[ServiceContract]     public interface IUpLoadService     {         [OperationContract(Action = "UploadFile", IsOneWay = true)]         void UploadFile(FileUploadMessage request);     }

[MessageContract]     public class FileUploadMessage     {         [MessageHeader(MustUnderstand = true)]         public string SavePath;

[MessageHeader(MustUnderstand = true)]         public string FileName;

[MessageBodyMember(Order = 1)]         public Stream FileData;

}

定义FileUploadMessage类的目的是因为第三个限制,要不然文件名和存放路径就没办法传递给WCF了,根据第二个限制,文件数据是用System.IO.Stream来传递的

接口方法只有一个,就是上传文件,注意方法参数是FileUploadMessage

接口实现类文件的代码如下:

public class UpLoadService : IUpLoadService     {         public void UploadFile(FileUploadMessage request)         {             string uploadFolder = @"C:\kkk\";             string savaPath = request.SavePath;             string dateString = DateTime.Now.ToShortDateString() + @"\";             string fileName = request.FileName;             Stream sourceStream = request.FileData;             FileStream targetStream = null;                        if (!sourceStream.CanRead)             {                 throw new Exception("数据流不可读!");             }             if (savaPath == null) savaPath = @"Photo\";             if (!savaPath.EndsWith("\\")) savaPath += "\\";

uploadFolder = uploadFolder + savaPath + dateString;             if (!Directory.Exists(uploadFolder))             {                 Directory.CreateDirectory(uploadFolder);             }

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

}

实现的功能是到指定目录下按照日期进行目录划分,然后以传过来的文件名保存文件。

这篇文章最主要的地方就是下面的Web.Config配置:

<system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="FileTransferServicesBinding" maxReceivedMessageSize="9223372036854775807"
          messageEncoding="Mtom" transferMode="Streamed" sendTimeout="00:10:00" />
          </basicHttpBinding>
    </bindings>
    <services>
      <service behaviorConfiguration="UploadWcfService.UpLoadServiceBehavior"
        name="UploadWcfService.UpLoadService">
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="FileTransferServicesBinding" contract="UploadWcfService.IUpLoadService">
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="UploadWcfService.UpLoadServiceBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

配置要遵循上面的第一条和第四条限制,因为默认.net只能传4M的文件,所以要在 <System.Web>配置节下面加上<httpRuntimemaxRequestLength="2097151" />

这样WCFService就完成了,新建一个Console项目或者Web项目测试一下。要注意的 是Client端的配置必须要和服务端一样,实例程序在这里下载。

利用WCF实现上传下载文件服务的更多相关文章

  1. 【WCF】利用WCF实现上传下载文件服务

    引言     前段时间,用WCF做了一个小项目,其中涉及到文件的上传下载.出于复习巩固的目的,今天简单梳理了一下,整理出来,下面展示如何一步步实现一个上传下载的WCF服务. 服务端 1.首先新建一个名 ...

  2. 【ARM-LInux开发】利用scp 远程上传下载文件/文件夹

    利用scp 远程上传下载文件/文件夹 scp [-1246BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file] [-l limit] [-o s ...

  3. 利用scp 远程上传下载文件/文件夹和ssh远程执行命令

    利用scp传输文件 1.从服务器下载文件scp username@servername:/path/filename /tmp/local_destination例如scp codinglog@192 ...

  4. 利用 secureCRT 直接上传下载文件 (sz,rz)

    在window下向linux传送文件的方法. 首先在window中安装SecureCRT,然后在快速连接中建立一个到linux的连接,当然,你要先知道你的系统的ip,在终端中键入ifconfig可以查 ...

  5. linux利用scp远程上传下载文件/文件夹

    scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的.可能会稍微影响一下速度. 当你服务 ...

  6. 利用scp 远程上传下载文件/文件夹

    scp [-1246BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file] [-l limit] [-o ssh_option] [-P port ...

  7. linux利用sh脚本上传下载文件到ftp服务器

    ####本地的/app/awsm/csv2 to ftp服务器上的/awsm/#### #!/bin/sh export today=`date +%Y-%m-%d` ftp -v -n 10.116 ...

  8. 如何利用京东云的对象存储(OSS)上传下载文件

    作者:刘冀 在公有云厂商里都有对象存储,京东云也不例外,而且也兼容S3的标准因此可以利用相关的工具去上传下载文件,本文主要记录一下利用CloudBerry Explorer for Amazon S3 ...

  9. shell通过ftp实现上传/下载文件

    直接代码,shell文件名为testFtptool.sh: #!/bin/bash ########################################################## ...

随机推荐

  1. SPOJ Meteors - 可持久化线段树 - 二分法

    Byteotian Interstellar Union (BIU) has recently discovered a new planet in a nearby galaxy. The plan ...

  2. Catogory如何添加属性

    一,Category结构体 typedef struct category_t { const char *name; //类的名字 classref_t cls; //类 struct method ...

  3. uniGUI试用笔记(八)

    在业务系统中常常使用回车键(Enter)替代Tab键完成焦点跳转,在uniGUI下,可以不用代码,直接使用TUniForm的NavigateKeys进行设置: 其中Next和Prior决定了焦点向下一 ...

  4. Python3基础 dict in/not in 查询一个字符是否指定字典的键或者值

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  5. Restful framework【第二篇】APIView

    安装djangorestframework 方式一:pip3 install djangorestframework 方式二:pycharm图形化界面安装 方式三:pycharm命令行下安装(装在当前 ...

  6. git如何将一个分支合并到另一个分支?

    答: git merge --no-edit <another branch>

  7. Win32汇编学习(4):绘制文本

    这次,我们将学习如何在窗口的客户区"绘制"字符串.我们还将学习关于"设备环境"的概念. 理论: "绘制"字符串 Windows 中的文本是一 ...

  8. Trimmomatic过滤Illumina低质量序列

    1. 下载安装 直接去官网下载二进制软件,解压后的trimmomatic-0.36.jar即为我们需要的软件 官网: http://www.usadellab.org/cms/index.php?pa ...

  9. P3211 [HNOI2011]XOR和路径

    思路 看到异或,容易联想到二进制位之间是相互独立的,所以可以把问题变成每个二进制位为1的概率再乘上(1<<pos)的值 假设现在考虑到pos位,设f[i]为第i个节点期望的异或和第pos位 ...

  10. 强化学习策略梯度方法之: REINFORCE 算法(从原理到代码实现)

    强化学习策略梯度方法之: REINFORCE 算法 (从原理到代码实现) 2018-04-01  15:15:42   最近在看policy gradient algorithm, 其中一种比较经典的 ...