WCF利用Stream上传大文件

利用Message Contract实现WCF上传大文件。

首先要准备一个数据载体类和WCF服务。

[ServiceContract]
    public interface IGetDataService
    {
        [OperationContract]
        void UploadFile(FileData file);
   }
[MessageContract]
    public class FileData
    {
        [MessageHeader]
      public string FilePath { set; get; }

      [MessageBodyMember(Order = 1)]
      public Stream FileData { set; get; }
    } 

接着是服务端具体实现方式。

[OperationContract]
public void UploadModelFile(FileUploadMessage physicalFile)
    {
        try
        {
            // upload file
            Stream sourceStream = physicalFile.FileData;
            if (!sourceStream.CanRead)
                throw new IOException("The input stream can not be read!");

            string uploadFolder = physicalFile.FilePath.Substring(0, physicalFile.FilePath.LastIndexOf("\\"));
            if (!Directory.Exists(uploadFolder))
                Directory.CreateDirectory(uploadFolder);

            using (FileStream fs = new FileStream(physicalFile.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)
                {
                    fs.Write(buffer, 0, count);
                }
                fs.Close();
                sourceStream.Close();
            }
        }
        catch (Exception ex)
        {
            LogManager.GetInstance().WriteErrorLog(string.Format("Upload Model File Fail! Message: {0}", ex.Message));
            throw ex;
        }
    } 

 最后使用WCF的Client类来调用服务就可以了。

 

代码实现过程中要注意两点:

1. 使用FileUploadMessage类作为输入参数的OperationContract方法的返回值类型(或者输入参数类型)必须是FileUploadMessage类中已使用的类型,比如FileUploadMessage类中的属性有string和stream,UploadModelFile方法的参数类型就只能是string或者stream类型,不然会报错。不过最保险还是返回void,这样就不会错。

 2. 也是UploadModelFile方法的参数类型问题,以标记为MessageContractAttribute的参数类型不能和标记成DataContractAttribute的参数混用,不然也会报错。

 

 WCF配置过程中要注意:

1. 在使用WCF服务的Client端的配置文件中,记得设置maxBufferSize的值和maxReceivedMessageSize的值,不然文件一大就报错了,这里的单位是字节。

<bindings>
<
basicHttpBinding>
<
binding name="BasicHttpBinding_WcfService" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<
security mode="None" />
</
binding>
</
basicHttpBinding>
</
bindings>
2. 在编写WCF服务的Server端添加bindings节点
<bindings>
<
basicHttpBinding>
<
binding name="LargeDataTransferServicesBinding" maxReceivedMessageSize="2147483647"
messageEncoding="Text" transferMode="Streamed" sendTimeout="00:10:00" />
</
basicHttpBinding>
</
bindings>
这个节点貌似是默认没有帮你配置的,要自己手动添加,在system.serviceModel节点里面,然后在下载service的endpoint的basichttpbinding那个节点里加上bindingConfiguration="LargeDataTransferServicesBinding"属性。
<service behaviorConfiguration="FileTransferServiceBehavior"
name="FileTransferService">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="LargeDataTransferServicesBinding" contract="FileTransferService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
详细配置可以参考http://www.cnblogs.com/cuihongyu3503319/archive/2010/09/01/1814394.html。
 

你可能感兴趣的:(Stream)