使用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. CIL锁,GIL与线程池的区别,进程池和线程池,同步与异步

    一.GIL锁 什么是GIL? 全局解释器锁,是加在解释器上的互斥锁 GC是python自带的内存管理机制,GC的工作原理:python中的内存管理使用的是应用计数,每个数会被加上一个整型的计数器,表示 ...

  2. 为什么说 HashMap 是非线程安全的?

    我们在学习 HashMap 的时候,都知道 HashMap 是非线程安全的,同时我们知道 HashTable 是线程安全的,因为里面的方法使用了 synchronized 进行同步. 但是 HashM ...

  3. Python3 tkinter基础 Listbox Button 点击按钮删除选中的单个元素

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

  4. C#开发者工具网

    使用key值[123456]对[50cms]进行对称加密-在线DES对称加密/解密- 开发者工具网  http://tool.sufeinet.com/Encrypt/DesEncrypt.aspx? ...

  5. Python 解析 XML 文件生成 HTML

    XML文件result.xml,内容如下: <ccm> <metric> <complexity>1</complexity> <unit> ...

  6. windows进程中的几个杂项-hpguard 进程终止

    打印机后台进程 c:\windows\system32\spool printers,servers, tool等, 清空printers中的内容就可以正常打印; 锐爽的后视镜跟其他的车型的后视镜不一 ...

  7. win10+vscode部署java开发环境

    目录 Java开发插件配置: 调试: 快捷键: 启动配置文件launch.json: 启动配置说明: Launch: Attach: User Setting: 遇到的问题: 参考: Java开发插件 ...

  8. NodeJs完全迁移到D盘,形成绿色安装版

    查看npm配置 D:\Git\AG-Admin-v2. (master) $ npm config ls ; cli configs metrics-registry = "https:// ...

  9. C++中的string常用函数用法

    标准c++中string类函数介绍   注意不是CString 之所以抛弃char*的字符串而选用C++标准程序库中的string类,是因为他和前者比较起来,不必 担心内存是否足够.字符串长度等等,而 ...

  10. [蓝桥] 基础练习 十进制转十六进制 (java)

    问题描述 十六进制数是在程序设计时经常要使用到的一种整数的表示方式.它有0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F共16个符号,分别表示十进制数的0至15.十六进制的计数方法是满1 ...